常见问题
为什么不用第三方组件库?
基础控件基于 Radix 原语自建(src/components/ui/),后台语义组件自己实现。理由是:
- 主题一致性:颜色只走语义 Token,换配色时不需要跟组件库的主题变量打架;
- 无障碍可控:焦点管理、键盘行为、ARIA 属性都在自己手里,出问题能直接修;
- 包体:组件库往往带一整套用不到的样式与逻辑,模板只需要后台常用的这些。
代价是要自己维护这些组件,所以才有"组件总览 + 真实落点 + 测试"三件套约束。
为什么不引图表库?
折线、柱状、环形、迷你柱、条形、热力、雷达、漏斗、甘特都在 src/components/charts.tsx 与 column-chart.tsx 里自绘 SVG:跟随语义色、支持深色模式、支持"减少动效",包体几乎为零。 需要更复杂的图表(地图、金融 K 线、大数据量散点)时,建议在业务侧单独引库,不要改动这一层。
文档站为什么用 VitePress?
- 内容就是 Markdown:
docs/是站点根目录,guide/放指南、components/放组件,改文案不用碰 React 代码; - 主题能力开箱可用:导航、分组侧栏、目录大纲、深色模式、本地全文搜索都是内置的,不用自己维护一套文档站外壳;
- 构建即校验:
pnpm docs:build会检查死链,链接写错直接构建失败; - 产物是纯静态文件:
docs/.vitepress/dist丢到任意静态托管即可; - 依赖边界干净:只装在 devDependencies,不进应用产物,应用构建(
pnpm build)与文档构建互不影响。
需要代码分栏、任务清单这类增强时再按需加 VitePress 插件;当前只装了本体,保持依赖最少。
为什么偏好只存 localStorage?
主题、配色、无障碍、通知偏好、顶栏操作顺序、侧栏宽度 / 圆角 / 动画 / 布局模式、表格列宽、筛选预设、快捷键 都是"这台设备上的个人偏好",不需要服务端同步,也不该进 Zustand 的业务状态。所有键名都带 VITE_APP_STORAGE_PREFIX 前缀,多后台同域部署时互不干扰。
服务端数据为什么进不了 Zustand?
模板刻意不提供请求层:数据获取、缓存、失效策略各业务差异太大,写进来反而会互相打架。 Zustand 只放本地 UI 状态与偏好,接口数据请用业务自己的请求方案(TanStack Query、SWR、自研都可以)。
新增页面后菜单没出现?
检查三处:
src/App.tsx有没有注册路由;src/app/navigation.ts的navigation有没有登记path/label/icon;navigationGroups的paths有没有把路径放进期望的分组——未登记的会落到第一个分组。
命令面板搜不到新页面的内容?
命令面板索引的是"渲染出来的页面内容",上限 400 条,按路由缓存,页面内容变化通过 MutationObserver 重建索引。 如果内容由异步请求填充,需要在数据到位后再打开面板;如果页面特别大,可以把索引上限调大或改为分片索引。
虚拟滚动的表格为什么必须固定行高?
虚拟滚动靠"行高 × 行数"算总高度和窗口位置。当前实现按固定行高渲染可视窗口(并让表头吸顶), 所以与行内展开互斥;需要动态行高时要改成按行测量 + 滚动锚定, 这是架构与决策里记录的已知取舍。
表格的滚动容器为什么不能随手改成 overflow-x-auto?
虚拟滚动依赖外层容器作为滚动锚点。给内层 .table-container 加横向滚动会把滚动事件抢走, 表头就不再吸顶。改表格样式时先确认虚拟滚动用例(design-system.spec.ts)仍然通过。
asChild 和 loading 为什么不能一起用?
Radix 的 Slot 只接受单个子元素,而加载态需要插入转圈图标。Button 现在的处理是: asChild 时只保留禁用语义、不插图标,避免出现"给 Slot 传了两个 children"导致整站崩溃。
文案不生效 / 页面显示成了 key?
两种情况:
- key 没登记进
src/lib/i18n.ts——pnpm test里的i18n-keys.test.ts会报出来; - 文案是动态拼接的 key —— 扫描覆盖不到,需要人工检查
t()的入参。
菜单项可以直接写中文(未登记的 key 原样显示),但组件内部固定文案必须进语言包。
顶栏通知为什么固定在第二位?
这是产品约定:通知是最高频的全局入口。用户仍可以在「设置 → 外观 → 顶栏快捷操作」里调整顺序, 新版本新增的入口会按默认位置插回,不会因为用户改过顺序就消失。
顶部导航模式下为什么看不到官网入口和品牌字标?
顶部导航(top)模式下,官方站点入口与品牌字标会从侧栏移除,避免与顶部导航重复: 侧边菜单由顶部菜单点击展开,面包屑与顶部菜单分两行,右上角只显示头像图标。这是刻意的视觉收敛, 不是渲染缺失。