Skip to content

07|组件库与设计系统 ​

第九章 / 07。目标:从真实组件合同与产物证据选库,不按截图、热度或组件数量投票。

先做一条垂直切片 ​

用同一个“异步提交表单”检验候选库:label 与错误关联、键盘提交、焦点恢复、loading/disabled、主题 token、SSR 输出、按需导入和测试定位。一个 Button demo 证明不了表单、弹层和日期选择器边界。

vue
<script setup lang="ts">
const props = defineProps<{ pending: boolean }>()
const emit = defineEmits<{ submit: [] }>()
</script>

<template>
  <VendorButton
    :loading="pending"
    :disabled="pending"
    @click="emit('submit')"
  >
    <slot />
  </VendorButton>
</template>

业务只依赖 AppSubmitButton 的小合同。若替换 VendorButton,调用页面和测试不必知道第三方 prop 名。但不要给每个基础组件都包一层空壳;只有需要统一语义、主题或迁移隔离时才值得。

打包身份与 CSS 都要验证 ​

开发组件库时,Vue 通常是 peerDependencies,并在库构建中 external,避免应用出现两份 Vue 运行时:

ts
export default defineConfig({
  build: {
    lib: { entry: 'src/index.ts', formats: ['es'] },
    rolldownOptions: { external: ['vue'] }
  }
})

Vite 8 使用 rolldownOptions;旧主版本常见 rollupOptions,维护旧项目时应按锁定版本核对。消费端实验要检查 npm ls vue/产物图、实际 import 后的 JS/CSS、主题样式顺序和 SSR hydration;“支持 tree shaking”只是声明,实际增量由导入方式和构建配置决定。

评估边界 ​

维度可验收证据
无障碍键盘路径、role/name、焦点 trap/恢复、错误关联
主题token 覆盖范围、暗色/高对比、升级 diff
SSR服务端无 browser global,首轮输出一致
维护版本策略、变更日志、Vue peer 范围、安全响应
体积真实应用 production build 的增量,不引用官网固定数字

先固定上游接口,再写适配器 ​

适配不是给相同属性换一个名字就结束。假设候选供应方约定 visible 输入,dismiss/accept 输出:业务的 open 要映射 visible,dismiss 变 update:open(false),accept 在 pending=false 才允许变 confirm。焦点何时进入、关闭后回到哪里属于业务组件的合同,不能让调用页依赖供应方内部 class。

本节练习先用答案提供的 VendorDialog.vue 小替身固定这个协议,因此不需要先选或安装某个 UI 库。替身没有真实 focus trap;选定生产库后,用同一测试再验证库的焦点限制、Portal/Teleport、滚动锁和原生键盘行为。把替身通过当成该库已经通过是错误推论。

练习:做一个可替换适配器 ​

实现 AppDialog 合同:open prop、update:open 与 confirm 事件;打开后聚焦标题,Escape 关闭,关闭后焦点回到触发按钮,pending 是布尔 prop,true 时 confirm 不得发出;false 时一次点击恰发一次。先针对 visible/dismiss/accept 供应方协议与答案给出的替身写适配器和组件测试,再替换成实际候选库复核;测试只能依赖 AppDialog 合同,不得读取 Vendor 私有 class。

参考答案:第 9 章第 07 题。

用心记录每一步成长