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

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

毒舌时刻

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

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

为什么你需要组件库

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

反面教材

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

基于Java和高德开放平台的WebAPI集成实践-以搜索POI2.0为例

基于Java和高德开放平台的WebAPI集成实践-以搜索POI2.0为例

目录 前言 一、高德搜索API简介 1、高德开放平台 2、搜索功能介绍  3、部分API介绍 二、Uniapi集成高德API 1、API集成流程 2、访问接口的定义 3、业务调用集成 三、常见问题与优化 四、总结 前言         在当今数字化时代,地理信息系统(GIS)和位置服务(LBS)已成为许多应用程序的核心组成部分。无论是导航、物流、社交网络还是电子商务,位置数据的获取和处理都显得尤为重要。高德开放平台作为国内领先的地理信息服务提供商,提供了丰富的WebAPI接口,帮助开发者快速集成地图、导航、搜索等功能。其中,POI(Point of Interest)搜索是许多应用场景中的关键功能,它能够帮助用户快速找到附近的兴趣点,如餐馆、酒店、加油站等。         Java作为一种广泛使用的编程语言,因其跨平台性、

【前端高频面试题】 - TypeScript 篇

【前端高频面试题】—— TypeScript 篇(2025-2026 最新趋势版) 以下是目前大厂和中高级前端岗位最常问的 TypeScript 面试题,按出现频率和难度从高到低排序,涵盖基础、进阶、工程化、类型体操等多个维度。 基础 & 核心概念(几乎必问) 1. TypeScript 和 JavaScript 的主要区别是什么?TypeScript 的优势和劣势分别有哪些? 2. type 和 interface 有什么区别?什么场景下应该用哪个? 3. 什么是类型推断(Type Inference)?举几个常见的类型推断场景。 4. const 和 readonly 的区别?什么时候用 readonly? 5. 什么是类型兼容性(Type Compatibility)?结构类型系统和标称类型系统有什么区别? 6. any、unknown、

玩转ClaudeCode:使用Figma-MCP编写前端代码1:1还原UI设计图

玩转ClaudeCode:使用Figma-MCP编写前端代码1:1还原UI设计图

目录 本轮目标 具体实践 一、开启 Figma 的 MCP 服务器 二、Claude Code 连接 Figma MCP 三、Claude Code 代码实现 Figma 设计稿 本轮目标 本轮目标是制作数字化大屏的一个前端组件,要求和UI设计图还原度达到1:1。 本轮目标需要我们提前准备好figma客户端,且登录帐号具有开发模式的权限(没有可以去某夕)。Claude Code 就不必多说,没有安装的同学参考我的上一篇文章《玩转ClaudeCode:ClaudeCode安装教程(Windows+Linux+MacOS)》完成安装,通过专属链接注册,可以额外领取100美金的免费使用额度。 安装教程参考:玩转ClaudeCode:ClaudeCode安装教程(Windows+Linux+MacOS)_claude code安装-ZEEKLOG博客文章浏览阅读2.5w次,点赞67次,

Flutter 与 Web 混合开发:跨平台的完美融合

Flutter 与 Web 混合开发:跨平台的完美融合

Flutter 与 Web 混合开发:跨平台的完美融合 写在前面 今天想和你聊聊一个让跨平台开发更具可能性的话题——Flutter 与 Web 混合开发。在我眼里,Flutter 就像一位多才多艺的艺术家,既能在移动平台上展现精彩,也能在 Web 世界中绽放光芒。 Flutter Web 的崛起 Flutter Web 是 Flutter 的一个重要方向,它允许我们使用同一套代码库构建运行在浏览器中的应用。随着 Flutter 3.0 的发布,Flutter Web 的性能和稳定性得到了显著提升,为混合开发开辟了新的可能。 Flutter Web 的优势 1. 代码复用:使用同一套代码库构建移动应用和 Web 应用,减少开发和维护成本 2. 一致的用户体验:在不同平台上提供一致的视觉和交互体验 3. 高性能: