用 Vite 与原生 CSS 搭建轻量 React 看板界面
译注:本文翻译自 dev.to 前端板块文章《Structuring a Lightweight React Kanban UI (Vanilla CSS & Vite)》,作者 Dhruv。原文链接见文末。文章以一个销售管道看板原型为例,讨论在不引入重型 UI 组件库的前提下,如何用 React、Vite 与原生 CSS 组织前端结构。
在构建内部工具或仪表盘原型时,人们很容易第一时间就安装 Material-UI、Ant Design 这类重型组件库。这些库确实功能强大,但对于许多早期原型来说,采用 Vite、React 加原生 CSS 的轻量方案,往往更容易定制、也更好维护。
本文以一个浅色主题的 CRM 仪表盘为例,梳理其前端架构。该界面采用看板式的销售管道布局。
技术范围
在看代码之前,先明确这个示例到底包含什么。
它是什么:
- 一个静态的前端 UI 原型
- 一个用 Vite 构建的 React 应用
- 一个响应式的看板式布局
- 静态的模拟 CRM 数据
- 原生 CSS 样式
- 用 React 的
useState实现的基础菜单状态
它不是什么:
- 一个生产级 CRM
- 一个后端应用
- 一个连接数据库的系统
- 一个集成 API 的应用
- 一个鉴权系统
- 一个支持拖拽的看板
这里的目标很简单:展示如何用 React 和标准 CSS 组织出一个干净的 CRM 风格前端。
React 组件
这样的仪表盘可以拆成两个主要区域:
- 用于导航的侧边栏
- 包含销售管道的主内容区
在这个原型中,我们用 React 的 useState hook 来在视觉上跟踪当前激活的导航项。管道本身使用静态模拟数据。
import { useState } from 'react';
import './index.css';
function App() {
const [activeMenu, setActiveMenu] = useState('pipeline');
const leads = {
new: [
{
id: 1,
name: 'Acme Corp',
value: '$5,000'
}
],
contacted: [
{
id: 3,
name: 'Wayne Ent',
value: '$8,200'
}
],
qualified: [
{
id: 5,
name: 'Oscorp',
value: '$25,000'
}
],
won: [
{
id: 6,
name: 'Globex',
value: '$14,000'
}
]
};
return (
<div className="crm-app">
{/* Sidebar Navigation */}
<aside className="sidebar-light">
<div className="brand">
<h1>LeadFlow CRM</h1>
</div>
<nav className="nav-menu">
<button
className={
activeMenu === 'dashboard'
? 'active'
: ''
}
onClick={() =>
setActiveMenu('dashboard')
}
>
Dashboard
</button>
<button
className={
activeMenu === 'pipeline'
? 'active'
: ''
}
onClick={() =>
setActiveMenu('pipeline')
}
>
Sales Pipeline
</button>
</nav>
</aside>
{/* Main Content */}
<main className="main-board">
<header className="board-header">
<h2>Sales Pipeline</h2>
<button className="btn-primary">
+ New Deal
</button>
</header>
{/* Kanban Board */}
<div className="kanban-board">
<div className="kanban-column">
<h3>New Leads</h3>
{leads.new.map((lead) => (
<div
className="kanban-card"
key={lead.id}
>
<h4>{lead.name}</h4>
<span className="value">
{lead.value}
</span>
</div>
))}
</div>
{/* Additional columns can be rendered here */}
</div>
</main>
</div>
);
}
export default App;CSS 布局
主布局可以完全用 CSS Flexbox 处理。根容器设为 flex 布局,让侧边栏和主仪表盘并排排列。
.crm-app {
display: flex;
height: 100vh;
overflow: hidden;
background-color: #f8fafc;
color: #0f172a;
}侧边栏
侧边栏使用固定宽度,当主仪表盘扩展时它不会被压缩。
.sidebar-light {
width: 260px;
background-color: #ffffff;
border-right: 1px solid #e2e8f0;
display: flex;
flex-direction: column;
flex-shrink: 0;
}这样可以让导航在视觉上保持稳定,同时主仪表盘内容保持弹性。
主仪表盘区域
主内容区占据剩余的屏幕空间。
.main-board {
flex-grow: 1;
display: flex;
flex-direction: column;
overflow-x: auto;
}横向看板布局
看板本身也是一个 flex 容器。每一列都有固定的最小宽度,这样当列数增加时,看板可以横向滚动。
.kanban-board {
display: flex;
padding: 32px;
gap: 24px;
overflow-x: auto;
flex-grow: 1;
align-items: flex-start;
}单个看板列
每个管道阶段由一个简单的列表示。
.kanban-column {
min-width: 280px;
width: 280px;
background-color: #f1f5f9;
border-radius: 12px;
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}列中的卡片随后可以展示这些信息:
- 公司名称
- 交易金额
- 状态
- 联系人信息
- 销售阶段
在这个原型中,数据是刻意保持静态的。
响应式行为
一个简单的媒体查询就能让布局适配更小的屏幕。例如:
@media (max-width: 768px) {
.crm-app {
flex-direction: column;
}
.sidebar-light {
width: 100%;
}
.kanban-board {
padding: 16px;
overflow-x: auto;
}
}这样可以把侧边栏移到仪表盘上方,并让看板在较小屏幕上保持横向可滚动。
这种方案的价值
1. 配置简单
这个原型不需要额外的 UI 组件库,配置因此保持简单,样式也完全由你直接掌控。
2. 开发流程快
Vite 提供了快速的开发体验,对典型前端项目而言,启动快、热模块替换也快。
3. 完全掌控样式
使用原生 CSS 意味着你可以掌控:
- 间距
- 字体排版
- 颜色
- 边框
- 阴影
- 响应式行为
而无需去覆盖某个组件库既有的设计系统。
4. 组件结构清晰
React 让仪表盘可以轻松拆成可复用的部分,例如:
- 侧边栏
- 头部
- 看板列
- 交易卡片
- 指标卡片
- 表格
- 表单
随着原型成长,这些部分可以拆分为独立组件。
重要限制
这个示例刻意只限于前端 UI 结构。它不包含:
- API 请求
- 鉴权
- 数据库存储
- 拖拽行为
- 真实 CRM 数据
- 后端业务逻辑
这些功能需要在这个轻量前端原型之外做进一步开发。
最终结果
只使用:
- React
- Vite
- 原生 CSS
- 静态模拟数据
你就可以构建出一个干净、响应式的 CRM 风格仪表盘原型,而不必立刻引入大型 UI 库或后端基础设施。当你需要验证界面、构建内部工具原型,或把现有线框图变成可用的前端时,这种方案会很有用。