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

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

毒舌时刻

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

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

为什么你需要组件库

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

反面教材

// 反面教材:手动编写组件 // 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

AI 原生架构:鸿蒙App的下一代形态

AI 原生架构:鸿蒙App的下一代形态

子玥酱(掘金 / 知乎 / ZEEKLOG / 简书 同名) 大家好,我是子玥酱,一名长期深耕在一线的前端程序媛 👩‍💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。 我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括前端工程化、小程序、React / RN、Flutter、跨端方案, 在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。 技术方向:前端 / 跨端 / 小程序 / 移动端工程化 内容平台:掘金、知乎、ZEEKLOG、简书 创作特点:实战导向、源码拆解、少空谈多落地 文章状态:长期稳定更新,大量原创输出 我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、

OpenManus 项目导论:从“手写”到“智能写作”的进化史

一、OpenManus 项目导论:从“手写”到“智能写作”的进化史 还记得那些熬夜码字的日子吗?从Word文档到Markdown编辑器,写作工具在进化,但核心模式始终没变——手动构思、手动组织、手动修改。直到2025年3月,MetaGPT团队开源了OpenManus,这个号称要“复刻商业产品Manus全栈能力”的框架,彻底改变了游戏规则。 🤖 什么是OpenManus?不只是“另一个AI写作工具” 如果你以为OpenManus就是个帮你润色句子的AI助手,那就太小看它了。这货本质上是一个通用AI智能体框架,核心突破在于能把复杂任务自动拆解成可并行执行的子任务链。 想象一下:你告诉它“帮我写一份10万字的行业分析报告”,传统AI可能给你一堆零散段落,而OpenManus会: 1. 自动规划:拆解成“市场调研→数据分析→章节撰写→图表生成→格式排版”等具体步骤 2. 智能执行:调用不同工具完成每个子任务(浏览器搜索、Python分析、文档生成) 3. 结果整合:

Toast拦截器与日志系统:Toaster如何实现调试与监控的完整教程

Toast拦截器与日志系统:Toaster如何实现调试与监控的完整教程 【免费下载链接】ToasterAndroid 吐司框架,专治 Toast 各种疑难杂症 项目地址: https://gitcode.com/gh_mirrors/to/Toaster Android开发中,Toast作为轻量级消息提示组件,调试和监控一直是个痛点。Toaster框架通过创新的拦截器机制和智能日志系统,为开发者提供了完整的调试与监控解决方案。本教程将深入解析Toaster如何实现Toast的精准追踪与智能监控,帮助开发者快速定位问题、优化用户体验。 🎯 Toaster框架的核心优势 Toaster不仅是一个Toast增强框架,更是一个完整的调试监控工具。它通过拦截器机制和日志系统,解决了传统Toast难以调试、无法追踪调用位置、缺乏监控能力的问题。在大型项目中,这些功能对于维护代码质量和用户体验至关重要。 🔍 Toast拦截器机制详解 Toaster的拦截器机制基于IToastInterceptor接口设计,这是一个高度可扩展的架构: 拦截器接口设计 在library/src/

2026脑机共生记忆革命:当GitHub Copilot遇见CRITIC模型,程序员如何重构认知架构

2026脑机共生记忆革命:当GitHub Copilot遇见CRITIC模型,程序员如何重构认知架构

摘要:本文基于斯坦福大学2024年认知神经科学实验室的真实研究数据,结合微软GitHub Copilot在2025年Q4发布的开发者认知负荷报告,首次系统论证非侵入式脑机接口与AI代码助手协同工作时,开发者前额叶皮层认知资源释放可达17.3%的生理机制。我们将以微软亚洲研究院真实推行的"CodeMind"认知增强项目为案例,深度拆解CRITIC知识内化标准在软件工程场景中的量化和编码实践,并提供可直接部署的Python知识分类器和Mermaid架构图。全文所有数据均来自IEEE、ACM会议论文及企业技术博客公开渠道,拒绝任何虚构。 一、从"Google效应"到"Copilot依赖症":记忆外包的临界点危机 2011年,哥伦比亚大学心理学系Betsy Sparrow团队在《Science》发表的里程碑研究揭示:当人类意识到信息可被搜索引擎随时调取时,大脑会主动降低对该信息的编码强度,转而去记忆"如何找到它"的位置信息。这种现象在软件工程领域演变为更极端的形态——2025年Stack Overflow开发者调研显示, 83.7%的程序员承认遇到语法错误时第一反应是复制粘贴给ChatG