前端组件库:别再重复造轮子了

前端组件库:别再重复造轮子了

毒舌时刻

这组件写得跟拼凑似的,一点都不统一。

各位前端同行,咱们今天聊聊前端组件库。别告诉我你还在手动编写所有组件,那感觉就像在没有工具的情况下盖房子——能盖,但效率低得可怜。

为什么你需要组件库

最近看到一个项目,每个组件都要手动编写,样式不统一,维护困难。我就想问:你是在做组件还是在做重复劳动?

反面教材

// 反面教材:手动编写组件 // Button.jsx import React from 'react'; function Button({ children, onClick }) { return ( <button onClick={onClick} style={{ padding: '10px 20px', backgroundColor: '#007bff', color: '#fff', border: 'none', borderRadius: '4px', cursor: 'pointer' }} > {children} </button> ); } export default Button; // Input.jsx import React from 'react'; function Input({ value, onChange, placeholder }) { return ( <input type="text" value={value} onChange={onChange} placeholder={placeholder} style={{ padding: '10px', border: '1px solid #ddd', borderRadius: '4px', width: '100%' }} /> ); } export default Input; // Card.jsx import React from 'react'; function Card({ children }) { return ( <div style={{ padding: '20px', border: '1px solid #ddd', borderRadius: '4px', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' }} > {children} </div> ); } export default Card; 

毒舌点评:这组件编写,就像在重复造轮子,每个组件都要手动编写样式,效率低得可怜。

正确姿势

1. Ant Design

// 正确姿势:Ant Design // 1. 安装依赖 // npm install antd // 2. 基本使用 import React from 'react'; import { Button, Input, Card, Form, Table, Modal, notification } from 'antd'; import 'antd/dist/reset.css'; function App() { const [isModalVisible, setIsModalVisible] = React.useState(false); const showModal = () => { setIsModalVisible(true); }; const handleOk = () => { setIsModalVisible(false); notification.success({ message: '成功', description: '操作成功', }); }; const handleCancel = () => { setIsModalVisible(false); }; const columns = [ { title: '姓名', dataIndex: 'name', key: 'name', }, { title: '年龄', dataIndex: 'age', key: 'age', }, { title: '操作', key: 'action', render: () => ( <Button type="primary">编辑</Button> ), }, ]; const data = [ { key: '1', name: '张三', age: 32, }, { key: '2', name: '李四', age: 42, }, ]; return ( <div style={{ padding: '20px' }}> <Card title="用户管理"> <Button type="primary" onClick={showModal} style={{ marginBottom: '20px' }}> 添加用户 </Button> <Table columns={columns} dataSource={data} /> </Card> <Modal title="添加用户" open={isModalVisible} onOk={handleOk} onCancel={handleCancel} > <Form> <Form.Item label="姓名" name="name" rules={[{ required: true, message: '请输入姓名' }]} > <Input placeholder="请输入姓名" /> </Form.Item> <Form.Item label="年龄" name="age" rules={[{ required: true, message: '请输入年龄' }]} > <Input type="number" placeholder="请输入年龄" /> </Form.Item> </Form> </Modal> </div> ); } export default App; 

2. Material UI

// 正确姿势:Material UI // 1. 安装依赖 // npm install @mui/material @emotion/react @emotion/styled // 2. 基本使用 import React from 'react'; import { Button, TextField, Card, CardContent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Modal, Box } from '@mui/material'; function App() { const [isModalVisible, setIsModalVisible] = React.useState(false); const [name, setName] = React.useState(''); const [age, setAge] = React.useState(''); const showModal = () => { setIsModalVisible(true); }; const handleClose = () => { setIsModalVisible(false); }; const handleSubmit = () => { console.log('提交:', { name, age }); setIsModalVisible(false); }; const rows = [ { id: 1, name: '张三', age: 32 }, { id: 2, name: '李四', age: 42 }, ]; return ( <div style={{ padding: '20px' }}> <Card sx={{ mb: 2 }}> <CardContent> <Button variant="contained" color="primary" onClick={showModal} sx={{ mb: 2 }} > 添加用户 </Button> <TableContainer component={Paper}> <Table> <TableHead> <TableRow> <TableCell>姓名</TableCell> <TableCell>年龄</TableCell> <TableCell>操作</TableCell> </TableRow> </TableHead> <TableBody> {rows.map((row) => ( <TableRow key={row.id}> <TableCell>{row.name}</TableCell> <TableCell>{row.age}</TableCell> <TableCell> <Button variant="outlined" color="primary"> 编辑 </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> </CardContent> </Card> <Modal open={isModalVisible} onClose={handleClose} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > <Box sx={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', width: 400, bgcolor: 'background.paper', border: '2px solid #000', boxShadow: 24, p: 4, }}> <h2>添加用户</h2> <TextField label="姓名" fullWidth value={name} onChange={(e) => setName(e.target.value)} /> <TextField label="年龄" type="number" fullWidth value={age} onChange={(e) => setAge(e.target.value)} /> <Box sx={{ mt: 2, display: 'flex', justifyContent: 'flex-end', gap: 1 }}> <Button onClick={handleClose}>取消</Button> <Button variant="contained" color="primary" onClick={handleSubmit}> 提交 </Button> </Box> </Box> </Modal> </div> ); } export default App; 

3. Tailwind CSS + Shadcn UI

// 正确姿势:Tailwind CSS + Shadcn UI // 1. 安装依赖 // npm install -D tailwindcss postcss autoprefixer // npx tailwindcss init -p // npx shadcn@latest init // 2. 配置 Tailwind CSS // tailwind.config.js /** @type {import('tailwindcss').Config} */ export default { content: [ "./index.html", "./src/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], } // 3. 基本使用 import React from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Table, TableBody, TableCell, TableHead, TableRow } from '@/components/ui/table'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Label } from '@/components/ui/label'; function App() { const rows = [ { id: 1, name: '张三', age: 32 }, { id: 2, name: '李四', age: 42 }, ]; return ( <div className="p-4"> <Card className="mb-4"> <CardHeader> <CardTitle>用户管理</CardTitle> </CardHeader> <CardContent> <Dialog> <DialogTrigger asChild> <Button className="mb-4">添加用户</Button> </DialogTrigger> <DialogContent className="sm:max-w-md"> <DialogHeader> <DialogTitle>添加用户</DialogTitle> </DialogHeader> <div className="grid gap-4 py-4"> <div className="grid gap-2"> <Label htmlFor="name">姓名</Label> <Input placeholder="请输入姓名" /> </div> <div className="grid gap-2"> <Label htmlFor="age">年龄</Label> <Input type="number" placeholder="请输入年龄" /> </div> </div> <div className="flex justify-end gap-2"> <Button variant="secondary">取消</Button> <Button>提交</Button> </div> </DialogContent> </Dialog> <div className="overflow-auto"> <Table> <TableHead> <TableRow> <TableCell>姓名</TableCell> <TableCell>年龄</TableCell> <TableCell>操作</TableCell> </TableRow> </TableHead> <TableBody> {rows.map((row) => ( <TableRow key={row.id}> <TableCell>{row.name}</TableCell> <TableCell>{row.age}</TableCell> <TableCell> <Button variant="secondary">编辑</Button> </TableCell> </TableRow> ))} </TableBody> </Table> </div> </CardContent> </Card> </div> ); } export default App; 

毒舌点评:这才叫前端组件库,统一的样式,丰富的组件,开发效率高,再也不用担心重复造轮子的问题了。

Read more

找智能家居硬件开源项目?别只盯着GitHub,这几条路子更野

做智能家居硬件开发,最难的不是写代码,而是“不知道自己不知道什么”。明明想要找一个现成的开源传感器方案,结果在GitHub搜了半天,关键词换来换去,捞上来的要么是五年前的废弃库,要么是跟项目半毛钱关系都没有的Demo。 其实,找开源项目这件事,渠道比关键词重要得多。不同目的、不同阶段的开发需求,对应的“入口”完全不一样。下面这几条路子,是我自己这两年跑项目攒下来的,希望能帮你少走点弯路。 1.  如果你只是想要“一套能跑通的全屋智能方案” 这种情况最常见:你不想从零搭,想要一个社区活跃、插件多、文档友好的成熟平台,拿来改改就能用。 首选肯定是Home Assistant 。 这项目在GitHub上有7万多星,支持2000多种设备品牌,从米家到飞利浦到vivo全能接。关键是它的HACS商店(Home Assistant Community Store)完全就是开源项目的“应用市场”,你不需要自己搜仓库,直接在HACS里搜“Xiaomi”“Tuya”“Zigbee”,一键下载、重启、配置,半小时就能把全屋设备接进去

dify平台集成OCR:低代码+AI模型打造智能表单识别系统

dify平台集成OCR:低代码+AI模型打造智能表单识别系统 📖 项目背景与技术选型动因 在企业数字化转型过程中,大量纸质表单、发票、合同等非结构化文档需要转化为可处理的结构化数据。传统人工录入方式效率低、成本高、易出错,而通用OCR服务往往对中文支持不完善,尤其在复杂背景或手写体场景下识别准确率骤降。 为此,我们基于 dify 低代码平台,集成了一套轻量级但高精度的 OCR 文字识别系统。该系统采用经典的 CRNN(Convolutional Recurrent Neural Network)模型架构,专为中英文混合文本识别优化,在无GPU依赖的前提下实现 <1秒 的平均响应时间,真正做到了“开箱即用”的工业级OCR能力。 本方案的核心价值在于: - 低代码集成:通过dify平台快速接入AI能力,无需深度开发即可构建智能表单应用 - 高识别精度:相比传统轻量模型,CRNN在中文长文本、模糊图像、倾斜排版等复杂场景下表现更优 - 双模输出支持:同时提供可视化Web界面和标准REST API,

【无人机】无人机路径规划算法

【无人机】无人机路径规划算法

目录 一、引言:无人机与路径规划算法 二、路径规划算法基础 (一)定义与重要性 (二)规划目标与约束条件 三、常见路径规划算法详解 (一)A * 算法 (二)Dijkstra 算法 (三)RRT(快速扩展随机树)算法 (四)蚁群算法 四、算法应用实例与效果展示 (一)不同场景下的算法应用 (二)算法性能对比数据 五、算法的优化与发展趋势 (一)现有算法的优化策略 (二)结合新技术的发展方向 六、挑战与展望 (一)面临的技术挑战 (二)未来应用前景 七、结论 一、引言:无人机与路径规划算法 在科技飞速发展的今天,无人机作为一种极具创新性的技术产物,已深度融入我们生活的方方面面,

基于视觉语言动作的竞速无人机自主导航RaceVLA深度代码解析

基于视觉语言动作的竞速无人机自主导航RaceVLA深度代码解析

论文链接:https://arxiv.org/pdf/2503.02572 项目主页:https://racevla.github.io/ 代码仓库:https://github.com/SerValera/RaceVLA 0. 简介 RaceVLA项目标志着具身智能在无人机领域的重大突破。这是首次将视觉语言动作(Vision-Language-Action,VLA)模型成功应用于高速竞速无人机的自主导航系统。与传统的基于规划或轨迹生成的方法不同,RaceVLA实现了从视觉感知到飞行控制的端到端学习,能够理解自然语言指令并在动态环境中执行复杂的飞行任务。 该项目的核心创新在于将斯坦福大学开发的OpenVLA模型成功移植并优化到无人机平台上,通过处理第一视角(FPV)视频流和自然语言指令,直接生成包含三个线性速度和偏航角速度的4D控制向量。这种设计使得无人机能够像人类飞行员一样,基于视觉信息和任务理解做出实时的飞行决策,在不熟悉的环境中展现出卓越的导航能力。更令人瞩目的是,RaceVLA在泛化能力方面的表现尤为突出,在动态环境测试中,该系统在运动泛化和语义泛化方面显著优于Open