[{"data":1,"prerenderedAt":2487},["ShallowReactive",2],{"article-/topics/design/design-system-performance-guide":3,"related-design":855,"content-query-LuekFXHkN2":1793},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"image":11,"head":12,"body":17,"_type":849,"_id":850,"_source":851,"_file":852,"_stem":853,"_extension":854},"/topics/design/design-system-performance-guide","design",false,"","设计系统性能优化完整指南","深入解析设计系统的性能优化策略，涵盖组件懒加载、样式优化、Tree Shaking、打包策略等核心技术","2026-01-01","/images/topics/design/design-system-performance.jpg",{"meta":13},[14],{"name":15,"content":16},"keywords","设计系统性能,组件优化,Tree Shaking,懒加载,CSS优化,打包优化",{"type":18,"children":19,"toc":808},"root",[20,27,33,38,43,166,172,177,183,193,199,210,215,226,231,240,245,254,263,268,273,282,287,296,301,312,318,323,332,338,349,355,364,369,378,387,392,397,406,411,420,425,434,439,448,453,459,468,473,482,487,498,503,508,517,522,531,536,738,743,748,803],{"type":21,"tag":22,"props":23,"children":24},"element","h2",{"id":8},[25],{"type":26,"value":8},"text",{"type":21,"tag":28,"props":29,"children":30},"p",{},[31],{"type":26,"value":32},"设计系统作为应用的基础设施，其性能直接影响整体用户体验。本文将系统讲解设计系统的性能优化策略，帮助团队构建高性能的组件库。",{"type":21,"tag":22,"props":34,"children":36},{"id":35},"设计系统性能挑战",[37],{"type":26,"value":35},{"type":21,"tag":28,"props":39,"children":40},{},[41],{"type":26,"value":42},"常见的设计系统性能问题：",{"type":21,"tag":44,"props":45,"children":46},"table",{},[47,71],{"type":21,"tag":48,"props":49,"children":50},"thead",{},[51],{"type":21,"tag":52,"props":53,"children":54},"tr",{},[55,61,66],{"type":21,"tag":56,"props":57,"children":58},"th",{},[59],{"type":26,"value":60},"问题类型",{"type":21,"tag":56,"props":62,"children":63},{},[64],{"type":26,"value":65},"具体表现",{"type":21,"tag":56,"props":67,"children":68},{},[69],{"type":26,"value":70},"影响范围",{"type":21,"tag":72,"props":73,"children":74},"tbody",{},[75,94,112,130,148],{"type":21,"tag":52,"props":76,"children":77},{},[78,84,89],{"type":21,"tag":79,"props":80,"children":81},"td",{},[82],{"type":26,"value":83},"包体积过大",{"type":21,"tag":79,"props":85,"children":86},{},[87],{"type":26,"value":88},"首次加载缓慢",{"type":21,"tag":79,"props":90,"children":91},{},[92],{"type":26,"value":93},"首屏性能、带宽消耗",{"type":21,"tag":52,"props":95,"children":96},{},[97,102,107],{"type":21,"tag":79,"props":98,"children":99},{},[100],{"type":26,"value":101},"组件渲染慢",{"type":21,"tag":79,"props":103,"children":104},{},[105],{"type":26,"value":106},"交互卡顿",{"type":21,"tag":79,"props":108,"children":109},{},[110],{"type":26,"value":111},"用户体验、响应性",{"type":21,"tag":52,"props":113,"children":114},{},[115,120,125],{"type":21,"tag":79,"props":116,"children":117},{},[118],{"type":26,"value":119},"样式冗余",{"type":21,"tag":79,"props":121,"children":122},{},[123],{"type":26,"value":124},"CSS 文件过大",{"type":21,"tag":79,"props":126,"children":127},{},[128],{"type":26,"value":129},"解析时间、内存占用",{"type":21,"tag":52,"props":131,"children":132},{},[133,138,143],{"type":21,"tag":79,"props":134,"children":135},{},[136],{"type":26,"value":137},"依赖膨胀",{"type":21,"tag":79,"props":139,"children":140},{},[141],{"type":26,"value":142},"node_modules 庞大",{"type":21,"tag":79,"props":144,"children":145},{},[146],{"type":26,"value":147},"安装时间、构建效率",{"type":21,"tag":52,"props":149,"children":150},{},[151,156,161],{"type":21,"tag":79,"props":152,"children":153},{},[154],{"type":26,"value":155},"运行时开销",{"type":21,"tag":79,"props":157,"children":158},{},[159],{"type":26,"value":160},"动态计算过多",{"type":21,"tag":79,"props":162,"children":163},{},[164],{"type":26,"value":165},"CPU 占用、电池消耗",{"type":21,"tag":22,"props":167,"children":169},{"id":168},"tree-shaking-优化",[170],{"type":26,"value":171},"Tree Shaking 优化",{"type":21,"tag":28,"props":173,"children":174},{},[175],{"type":26,"value":176},"Tree Shaking 是减小包体积最有效的方法，确保只打包实际使用的代码。",{"type":21,"tag":178,"props":179,"children":181},"h3",{"id":180},"包结构设计",[182],{"type":26,"value":180},{"type":21,"tag":184,"props":185,"children":187},"pre",{"code":186},"packages/ui/\n├── src/\n│   ├── components/\n│   │   ├── Button/\n│   │   │   ├── index.ts\n│   │   │   ├── Button.vue\n│   │   │   └── Button.css\n│   │   ├── Input/\n│   │   │   └── ...\n│   │   └── index.ts        # 统一导出\n│   ├── composables/\n│   │   ├── useDialog.ts\n│   │   └── index.ts\n│   └── index.ts            # 主入口\n├── dist/\n│   ├── es/                 # ES Module 格式\n│   │   ├── components/\n│   │   │   ├── Button/\n│   │   │   │   └── index.mjs\n│   │   │   └── ...\n│   │   └── index.mjs\n│   ├── lib/                # CommonJS 格式\n│   └── types/              # 类型声明\n└── package.json\n",[188],{"type":21,"tag":189,"props":190,"children":191},"code",{"__ignoreMap":7},[192],{"type":26,"value":186},{"type":21,"tag":178,"props":194,"children":196},{"id":195},"packagejson-配置",[197],{"type":26,"value":198},"package.json 配置",{"type":21,"tag":184,"props":200,"children":205},{"code":201,"language":202,"meta":7,"className":203},"{\n  \"name\": \"@company/ui\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"./dist/lib/index.cjs\",\n  \"module\": \"./dist/es/index.mjs\",\n  \"types\": \"./dist/types/index.d.ts\",\n  \"sideEffects\": [\n    \"**/*.css\",\n    \"**/*.scss\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/types/index.d.ts\",\n      \"import\": \"./dist/es/index.mjs\",\n      \"require\": \"./dist/lib/index.cjs\"\n    },\n    \"./components/*\": {\n      \"types\": \"./dist/types/components/*/index.d.ts\",\n      \"import\": \"./dist/es/components/*/index.mjs\",\n      \"require\": \"./dist/lib/components/*/index.cjs\"\n    },\n    \"./composables\": {\n      \"types\": \"./dist/types/composables/index.d.ts\",\n      \"import\": \"./dist/es/composables/index.mjs\"\n    },\n    \"./styles/*\": \"./dist/styles/*\"\n  }\n}\n","json",[204],"language-json",[206],{"type":21,"tag":189,"props":207,"children":208},{"__ignoreMap":7},[209],{"type":26,"value":201},{"type":21,"tag":178,"props":211,"children":213},{"id":212},"组件导出方式",[214],{"type":26,"value":212},{"type":21,"tag":184,"props":216,"children":221},{"code":217,"language":218,"meta":7,"className":219},"// src/components/index.ts\n// 使用具名导出而非默认导出，便于 Tree Shaking\n\n// 推荐：具名导出\nexport { Button } from './Button'\nexport { Input } from './Input'\nexport { Select } from './Select'\nexport { Modal } from './Modal'\nexport { Table } from './Table'\n\n// 不推荐：对象导出（会阻止 Tree Shaking）\n// export default { Button, Input, Select, Modal, Table }\n","typescript",[220],"language-typescript",[222],{"type":21,"tag":189,"props":223,"children":224},{"__ignoreMap":7},[225],{"type":26,"value":217},{"type":21,"tag":178,"props":227,"children":229},{"id":228},"按需导入方式",[230],{"type":26,"value":228},{"type":21,"tag":184,"props":232,"children":235},{"code":233,"language":218,"meta":7,"className":234},"// 方式一：直接导入具体组件（最优）\nimport { Button } from '@company/ui/components/Button'\nimport { Input } from '@company/ui/components/Input'\n\n// 方式二：从主入口导入（依赖 Tree Shaking）\nimport { Button, Input } from '@company/ui'\n\n// 方式三：使用自动导入插件（无需手动导入）\n// 配置后直接在模板中使用组件\n",[220],[236],{"type":21,"tag":189,"props":237,"children":238},{"__ignoreMap":7},[239],{"type":26,"value":233},{"type":21,"tag":178,"props":241,"children":243},{"id":242},"自动导入配置",[244],{"type":26,"value":242},{"type":21,"tag":184,"props":246,"children":249},{"code":247,"language":218,"meta":7,"className":248},"// vite.config.ts\nimport Components from 'unplugin-vue-components/vite'\nimport { CompanyUIResolver } from '@company/ui/resolver'\n\nexport default defineConfig({\n  plugins: [\n    Components({\n      resolvers: [\n        CompanyUIResolver({\n          importStyle: 'css'  // 自动导入样式\n        })\n      ]\n    })\n  ]\n})\n",[220],[250],{"type":21,"tag":189,"props":251,"children":252},{"__ignoreMap":7},[253],{"type":26,"value":247},{"type":21,"tag":184,"props":255,"children":258},{"code":256,"language":218,"meta":7,"className":257},"// packages/ui/resolver.ts\n// 自定义解析器实现\nexport function CompanyUIResolver(options = {}) {\n  return {\n    type: 'component',\n    resolve: (name: string) => {\n      // 匹配组件名前缀\n      if (name.startsWith('Cu')) {\n        const componentName = name.slice(2)  // 去掉前缀\n        return {\n          name: componentName,\n          from: `@company/ui/components/${componentName}`,\n          sideEffects: options.importStyle \n            ? `@company/ui/styles/${componentName}.css`\n            : undefined\n        }\n      }\n    }\n  }\n}\n",[220],[259],{"type":21,"tag":189,"props":260,"children":261},{"__ignoreMap":7},[262],{"type":26,"value":256},{"type":21,"tag":22,"props":264,"children":266},{"id":265},"组件懒加载策略",[267],{"type":26,"value":265},{"type":21,"tag":178,"props":269,"children":271},{"id":270},"动态导入组件",[272],{"type":26,"value":270},{"type":21,"tag":184,"props":274,"children":277},{"code":275,"language":218,"meta":7,"className":276},"// 异步组件定义\nimport { defineAsyncComponent } from 'vue'\n\n// 基础用法\nconst AsyncModal = defineAsyncComponent(() => \n  import('./components/Modal/Modal.vue')\n)\n\n// 带加载状态和错误处理\nconst AsyncChart = defineAsyncComponent({\n  loader: () => import('./components/Chart/Chart.vue'),\n  loadingComponent: LoadingSpinner,\n  errorComponent: ErrorFallback,\n  delay: 200,           // 延迟显示 loading\n  timeout: 10000,       // 超时时间\n  suspensible: true     // 支持 Suspense\n})\n",[220],[278],{"type":21,"tag":189,"props":279,"children":280},{"__ignoreMap":7},[281],{"type":26,"value":275},{"type":21,"tag":178,"props":283,"children":285},{"id":284},"按路由分割组件",[286],{"type":26,"value":284},{"type":21,"tag":184,"props":288,"children":291},{"code":289,"language":218,"meta":7,"className":290},"// router/index.ts\nconst routes = [\n  {\n    path: '/dashboard',\n    component: () => import('@/layouts/DashboardLayout.vue'),\n    children: [\n      {\n        path: 'analytics',\n        // 按路由懒加载页面组件\n        component: () => import('@/pages/Analytics.vue')\n      },\n      {\n        path: 'reports',\n        component: () => import('@/pages/Reports.vue')\n      }\n    ]\n  }\n]\n",[220],[292],{"type":21,"tag":189,"props":293,"children":294},{"__ignoreMap":7},[295],{"type":26,"value":289},{"type":21,"tag":178,"props":297,"children":299},{"id":298},"按可见性懒加载",[300],{"type":26,"value":298},{"type":21,"tag":184,"props":302,"children":307},{"code":303,"language":304,"meta":7,"className":305},"\u003Ctemplate>\n  \u003Cdiv ref=\"containerRef\">\n    \u003Ccomponent \n      v-if=\"isVisible\" \n      :is=\"AsyncComponent\"\n      v-bind=\"$attrs\"\n    />\n    \u003Cdiv v-else class=\"placeholder\" :style=\"placeholderStyle\" />\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript setup lang=\"ts\">\nimport { useIntersectionObserver } from '@vueuse/core'\n\nconst props = defineProps\u003C{\n  loader: () => Promise\u003Cany>\n  rootMargin?: string\n  threshold?: number\n  placeholderHeight?: string\n}>()\n\nconst containerRef = ref\u003CHTMLElement>()\nconst isVisible = ref(false)\nconst AsyncComponent = shallowRef(null)\n\nconst { stop } = useIntersectionObserver(\n  containerRef,\n  ([{ isIntersecting }]) => {\n    if (isIntersecting) {\n      isVisible.value = true\n      // 开始加载组件\n      props.loader().then(module => {\n        AsyncComponent.value = module.default\n      })\n      stop()  // 停止观察\n    }\n  },\n  {\n    rootMargin: props.rootMargin || '100px',\n    threshold: props.threshold || 0\n  }\n)\n\nconst placeholderStyle = computed(() => ({\n  height: props.placeholderHeight || '200px'\n}))\n\u003C/script>\n","vue",[306],"language-vue",[308],{"type":21,"tag":189,"props":309,"children":310},{"__ignoreMap":7},[311],{"type":26,"value":303},{"type":21,"tag":22,"props":313,"children":315},{"id":314},"css-性能优化",[316],{"type":26,"value":317},"CSS 性能优化",{"type":21,"tag":178,"props":319,"children":321},{"id":320},"样式模块化",[322],{"type":26,"value":320},{"type":21,"tag":184,"props":324,"children":327},{"code":325,"language":218,"meta":7,"className":326},"// 构建配置：按组件分割样式\n// vite.config.ts\nexport default defineConfig({\n  build: {\n    cssCodeSplit: true,  // 启用 CSS 代码分割\n    rollupOptions: {\n      output: {\n        // 每个组件生成独立的 CSS 文件\n        assetFileNames: (assetInfo) => {\n          if (assetInfo.name?.endsWith('.css')) {\n            return 'styles/[name]-[hash][extname]'\n          }\n          return 'assets/[name]-[hash][extname]'\n        }\n      }\n    }\n  }\n})\n",[220],[328],{"type":21,"tag":189,"props":329,"children":330},{"__ignoreMap":7},[331],{"type":26,"value":325},{"type":21,"tag":178,"props":333,"children":335},{"id":334},"css-变量优化",[336],{"type":26,"value":337},"CSS 变量优化",{"type":21,"tag":184,"props":339,"children":344},{"code":340,"language":341,"meta":7,"className":342},"/* 避免过度使用 CSS 变量计算 */\n\n/* 不推荐：运行时计算 */\n.button {\n  padding: calc(var(--spacing-base) * 2) calc(var(--spacing-base) * 4);\n  font-size: calc(var(--font-size-base) * 1.125);\n}\n\n/* 推荐：预定义具体值 */\n.button {\n  padding: var(--button-padding-y) var(--button-padding-x);\n  font-size: var(--button-font-size);\n}\n\n/* 在根级别定义计算值 */\n:root {\n  --spacing-base: 4px;\n  --button-padding-y: 8px;   /* spacing-base * 2 */\n  --button-padding-x: 16px;  /* spacing-base * 4 */\n  --button-font-size: 14px;\n}\n","css",[343],"language-css",[345],{"type":21,"tag":189,"props":346,"children":347},{"__ignoreMap":7},[348],{"type":26,"value":340},{"type":21,"tag":178,"props":350,"children":352},{"id":351},"关键-css-提取",[353],{"type":26,"value":354},"关键 CSS 提取",{"type":21,"tag":184,"props":356,"children":359},{"code":357,"language":218,"meta":7,"className":358},"// 提取首屏关键 CSS\nimport { createCriticalCSS } from '@company/ui/build'\n\n// 构建时提取关键样式\nasync function extractCriticalCSS() {\n  const critical = await createCriticalCSS({\n    src: 'dist/index.html',\n    css: ['dist/styles/main.css'],\n    width: 1300,\n    height: 900,\n    // 关键组件列表\n    criticalComponents: [\n      'Button',\n      'Input',\n      'Layout',\n      'Header',\n      'Navigation'\n    ]\n  })\n  \n  return critical\n}\n",[220],[360],{"type":21,"tag":189,"props":361,"children":362},{"__ignoreMap":7},[363],{"type":26,"value":357},{"type":21,"tag":178,"props":365,"children":367},{"id":366},"样式作用域优化",[368],{"type":26,"value":366},{"type":21,"tag":184,"props":370,"children":373},{"code":371,"language":304,"meta":7,"className":372},"\u003Ctemplate>\n  \u003Cbutton class=\"btn\" :class=\"variantClass\">\n    \u003Cslot />\n  \u003C/button>\n\u003C/template>\n\n\u003Cstyle scoped>\n/* 使用 scoped 避免全局污染，但注意其实现方式 */\n.btn {\n  /* 基础样式 */\n}\n\u003C/style>\n\n\u003Cstyle>\n/* \n * 性能提示：\n * scoped 会为每个元素添加 data 属性\n * 对于频繁创建销毁的组件，考虑使用 CSS Modules\n */\n\u003C/style>\n",[306],[374],{"type":21,"tag":189,"props":375,"children":376},{"__ignoreMap":7},[377],{"type":26,"value":371},{"type":21,"tag":184,"props":379,"children":382},{"code":380,"language":304,"meta":7,"className":381},"\u003Ctemplate>\n  \u003Cbutton :class=\"$style.btn\">\n    \u003Cslot />\n  \u003C/button>\n\u003C/template>\n\n\u003Cstyle module>\n/* CSS Modules：类名在编译时替换，无运行时开销 */\n.btn {\n  padding: 8px 16px;\n  border-radius: 4px;\n}\n\u003C/style>\n",[306],[383],{"type":21,"tag":189,"props":384,"children":385},{"__ignoreMap":7},[386],{"type":26,"value":380},{"type":21,"tag":22,"props":388,"children":390},{"id":389},"运行时性能优化",[391],{"type":26,"value":389},{"type":21,"tag":178,"props":393,"children":395},{"id":394},"组件渲染优化",[396],{"type":26,"value":394},{"type":21,"tag":184,"props":398,"children":401},{"code":399,"language":304,"meta":7,"className":400},"\u003Ctemplate>\n  \u003C!-- 使用 v-memo 缓存静态内容 -->\n  \u003Cdiv v-memo=\"[item.id, item.status]\">\n    \u003CExpensiveComponent :data=\"item\" />\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript setup lang=\"ts\">\nimport { computed, shallowRef, markRaw } from 'vue'\n\n// 使用 shallowRef 避免深度响应\nconst tableData = shallowRef\u003CTableRow[]>([])\n\n// 非响应式对象使用 markRaw\nconst chartConfig = markRaw({\n  type: 'line',\n  options: { /* 大量配置 */ }\n})\n\n// 避免不必要的计算属性重新计算\nconst filteredData = computed(() => {\n  // 缓存计算结果\n  return expensiveFilter(tableData.value)\n})\n\u003C/script>\n",[306],[402],{"type":21,"tag":189,"props":403,"children":404},{"__ignoreMap":7},[405],{"type":26,"value":399},{"type":21,"tag":178,"props":407,"children":409},{"id":408},"虚拟化长列表",[410],{"type":26,"value":408},{"type":21,"tag":184,"props":412,"children":415},{"code":413,"language":304,"meta":7,"className":414},"\u003Ctemplate>\n  \u003CVirtualList\n    :items=\"items\"\n    :item-height=\"48\"\n    :buffer-size=\"5\"\n    key-field=\"id\"\n  >\n    \u003Ctemplate #default=\"{ item, index }\">\n      \u003CListItem :data=\"item\" :index=\"index\" />\n    \u003C/template>\n  \u003C/VirtualList>\n\u003C/template>\n\n\u003Cscript setup lang=\"ts\">\n// 虚拟列表组件实现核心逻辑\nfunction useVirtualList\u003CT>(options: VirtualListOptions\u003CT>) {\n  const { items, itemHeight, containerHeight, bufferSize = 3 } = options\n  \n  const scrollTop = ref(0)\n  \n  // 计算可见范围\n  const visibleRange = computed(() => {\n    const start = Math.floor(scrollTop.value / itemHeight)\n    const visibleCount = Math.ceil(containerHeight.value / itemHeight)\n    \n    return {\n      start: Math.max(0, start - bufferSize),\n      end: Math.min(items.value.length, start + visibleCount + bufferSize)\n    }\n  })\n  \n  // 只渲染可见项\n  const visibleItems = computed(() => {\n    const { start, end } = visibleRange.value\n    return items.value.slice(start, end).map((item, index) => ({\n      item,\n      index: start + index\n    }))\n  })\n  \n  // 计算偏移量\n  const offsetY = computed(() => visibleRange.value.start * itemHeight)\n  \n  // 计算总高度\n  const totalHeight = computed(() => items.value.length * itemHeight)\n  \n  return { visibleItems, offsetY, totalHeight, scrollTop }\n}\n\u003C/script>\n",[306],[416],{"type":21,"tag":189,"props":417,"children":418},{"__ignoreMap":7},[419],{"type":26,"value":413},{"type":21,"tag":178,"props":421,"children":423},{"id":422},"防抖与节流",[424],{"type":26,"value":422},{"type":21,"tag":184,"props":426,"children":429},{"code":427,"language":218,"meta":7,"className":428},"// composables/useDebounce.ts\nexport function useDebounce\u003CT extends (...args: any[]) => any>(\n  fn: T,\n  delay: number = 300\n) {\n  let timeoutId: ReturnType\u003Ctypeof setTimeout>\n  \n  const debouncedFn = (...args: Parameters\u003CT>) => {\n    clearTimeout(timeoutId)\n    timeoutId = setTimeout(() => fn(...args), delay)\n  }\n  \n  const cancel = () => clearTimeout(timeoutId)\n  \n  onUnmounted(cancel)\n  \n  return { debouncedFn, cancel }\n}\n\n// 使用示例\nconst { debouncedFn: debouncedSearch } = useDebounce(\n  (query: string) => searchAPI(query),\n  300\n)\n",[220],[430],{"type":21,"tag":189,"props":431,"children":432},{"__ignoreMap":7},[433],{"type":26,"value":427},{"type":21,"tag":178,"props":435,"children":437},{"id":436},"事件委托",[438],{"type":26,"value":436},{"type":21,"tag":184,"props":440,"children":443},{"code":441,"language":304,"meta":7,"className":442},"\u003Ctemplate>\n  \u003C!-- 使用事件委托处理大量子元素的事件 -->\n  \u003Cdiv class=\"list\" @click=\"handleClick\">\n    \u003Cdiv \n      v-for=\"item in items\" \n      :key=\"item.id\" \n      :data-id=\"item.id\"\n      class=\"list-item\"\n    >\n      {{ item.name }}\n    \u003C/div>\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript setup lang=\"ts\">\nfunction handleClick(event: MouseEvent) {\n  const target = event.target as HTMLElement\n  const listItem = target.closest('.list-item')\n  \n  if (listItem) {\n    const id = listItem.dataset.id\n    // 处理点击事件\n    handleItemClick(id)\n  }\n}\n\u003C/script>\n",[306],[444],{"type":21,"tag":189,"props":445,"children":446},{"__ignoreMap":7},[447],{"type":26,"value":441},{"type":21,"tag":22,"props":449,"children":451},{"id":450},"打包优化策略",[452],{"type":26,"value":450},{"type":21,"tag":178,"props":454,"children":456},{"id":455},"rollup-配置优化",[457],{"type":26,"value":458},"Rollup 配置优化",{"type":21,"tag":184,"props":460,"children":463},{"code":461,"language":218,"meta":7,"className":462},"// rollup.config.js\nimport { defineConfig } from 'rollup'\nimport vue from '@vitejs/plugin-vue'\nimport { terser } from 'rollup-plugin-terser'\nimport analyze from 'rollup-plugin-analyzer'\n\nexport default defineConfig({\n  input: {\n    index: 'src/index.ts',\n    // 按组件分割入口\n    ...getComponentEntries('src/components')\n  },\n  \n  output: [\n    {\n      dir: 'dist/es',\n      format: 'esm',\n      preserveModules: true,        // 保留模块结构\n      preserveModulesRoot: 'src',\n      entryFileNames: '[name].mjs',\n      exports: 'named'\n    },\n    {\n      dir: 'dist/lib',\n      format: 'cjs',\n      preserveModules: true,\n      preserveModulesRoot: 'src',\n      entryFileNames: '[name].cjs',\n      exports: 'named'\n    }\n  ],\n  \n  external: [\n    'vue',\n    /^@vue\\//,\n    // 外部化所有生产依赖\n    ...Object.keys(pkg.peerDependencies || {})\n  ],\n  \n  plugins: [\n    vue(),\n    terser({\n      compress: {\n        drop_console: true,\n        drop_debugger: true\n      }\n    }),\n    analyze({ summaryOnly: true })\n  ]\n})\n\n// 自动获取组件入口\nfunction getComponentEntries(dir: string) {\n  const components = fs.readdirSync(dir)\n  return components.reduce((entries, component) => {\n    const entryPath = path.join(dir, component, 'index.ts')\n    if (fs.existsSync(entryPath)) {\n      entries[`components/${component}/index`] = entryPath\n    }\n    return entries\n  }, {})\n}\n",[220],[464],{"type":21,"tag":189,"props":465,"children":466},{"__ignoreMap":7},[467],{"type":26,"value":461},{"type":21,"tag":178,"props":469,"children":471},{"id":470},"依赖外部化",[472],{"type":26,"value":470},{"type":21,"tag":184,"props":474,"children":477},{"code":475,"language":218,"meta":7,"className":476},"// 将大型依赖外部化，由消费者自行引入\nconst externalDeps = [\n  'vue',\n  'vue-router',\n  'pinia',\n  '@vueuse/core',\n  // 图表库等大型依赖\n  'echarts',\n  'chart.js'\n]\n\nexport default defineConfig({\n  external: (id) => {\n    return externalDeps.some(dep => id === dep || id.startsWith(`${dep}/`))\n  }\n})\n",[220],[478],{"type":21,"tag":189,"props":479,"children":480},{"__ignoreMap":7},[481],{"type":26,"value":475},{"type":21,"tag":178,"props":483,"children":485},{"id":484},"代码分析与优化",[486],{"type":26,"value":484},{"type":21,"tag":184,"props":488,"children":493},{"code":489,"language":490,"meta":7,"className":491},"# 使用 source-map-explorer 分析包体积\nnpx source-map-explorer dist/es/index.mjs\n\n# 使用 bundlephobia 查看依赖大小\n# https://bundlephobia.com/package/@company/ui\n","bash",[492],"language-bash",[494],{"type":21,"tag":189,"props":495,"children":496},{"__ignoreMap":7},[497],{"type":26,"value":489},{"type":21,"tag":22,"props":499,"children":501},{"id":500},"性能监控与测量",[502],{"type":26,"value":500},{"type":21,"tag":178,"props":504,"children":506},{"id":505},"组件性能指标",[507],{"type":26,"value":505},{"type":21,"tag":184,"props":509,"children":512},{"code":510,"language":218,"meta":7,"className":511},"// 性能监控 Hook\nexport function useComponentPerformance(componentName: string) {\n  const mountTime = ref(0)\n  const updateCount = ref(0)\n  const lastUpdateTime = ref(0)\n  \n  onMounted(() => {\n    mountTime.value = performance.now()\n    \n    // 记录挂载时间\n    if (import.meta.env.DEV) {\n      console.log(`[Perf] ${componentName} mounted in ${mountTime.value.toFixed(2)}ms`)\n    }\n  })\n  \n  onUpdated(() => {\n    updateCount.value++\n    lastUpdateTime.value = performance.now()\n    \n    // 检测频繁更新\n    if (import.meta.env.DEV && updateCount.value > 10) {\n      console.warn(`[Perf] ${componentName} updated ${updateCount.value} times`)\n    }\n  })\n  \n  return { mountTime, updateCount, lastUpdateTime }\n}\n",[220],[513],{"type":21,"tag":189,"props":514,"children":515},{"__ignoreMap":7},[516],{"type":26,"value":510},{"type":21,"tag":178,"props":518,"children":520},{"id":519},"性能基准测试",[521],{"type":26,"value":519},{"type":21,"tag":184,"props":523,"children":526},{"code":524,"language":218,"meta":7,"className":525},"// tests/performance/Button.bench.ts\nimport { describe, bench } from 'vitest'\nimport { mount } from '@vue/test-utils'\nimport { Button } from '@company/ui'\n\ndescribe('Button Performance', () => {\n  bench('mount Button', () => {\n    const wrapper = mount(Button, {\n      props: { variant: 'primary' }\n    })\n    wrapper.unmount()\n  })\n  \n  bench('mount 100 Buttons', () => {\n    const wrappers = Array.from({ length: 100 }, () => \n      mount(Button, { props: { variant: 'primary' } })\n    )\n    wrappers.forEach(w => w.unmount())\n  })\n  \n  bench('update Button props', async () => {\n    const wrapper = mount(Button, {\n      props: { variant: 'primary', loading: false }\n    })\n    \n    for (let i = 0; i \u003C 100; i++) {\n      await wrapper.setProps({ loading: i % 2 === 0 })\n    }\n    \n    wrapper.unmount()\n  })\n})\n",[220],[527],{"type":21,"tag":189,"props":528,"children":529},{"__ignoreMap":7},[530],{"type":26,"value":524},{"type":21,"tag":22,"props":532,"children":534},{"id":533},"性能优化清单",[535],{"type":26,"value":533},{"type":21,"tag":44,"props":537,"children":538},{},[539,565],{"type":21,"tag":48,"props":540,"children":541},{},[542],{"type":21,"tag":52,"props":543,"children":544},{},[545,550,555,560],{"type":21,"tag":56,"props":546,"children":547},{},[548],{"type":26,"value":549},"优化项",{"type":21,"tag":56,"props":551,"children":552},{},[553],{"type":26,"value":554},"优先级",{"type":21,"tag":56,"props":556,"children":557},{},[558],{"type":26,"value":559},"预期收益",{"type":21,"tag":56,"props":561,"children":562},{},[563],{"type":26,"value":564},"实施难度",{"type":21,"tag":72,"props":566,"children":567},{},[568,591,612,634,655,676,696,717],{"type":21,"tag":52,"props":569,"children":570},{},[571,576,581,586],{"type":21,"tag":79,"props":572,"children":573},{},[574],{"type":26,"value":575},"Tree Shaking 配置",{"type":21,"tag":79,"props":577,"children":578},{},[579],{"type":26,"value":580},"高",{"type":21,"tag":79,"props":582,"children":583},{},[584],{"type":26,"value":585},"减少 30-60% 体积",{"type":21,"tag":79,"props":587,"children":588},{},[589],{"type":26,"value":590},"低",{"type":21,"tag":52,"props":592,"children":593},{},[594,599,603,608],{"type":21,"tag":79,"props":595,"children":596},{},[597],{"type":26,"value":598},"按需导入",{"type":21,"tag":79,"props":600,"children":601},{},[602],{"type":26,"value":580},{"type":21,"tag":79,"props":604,"children":605},{},[606],{"type":26,"value":607},"减少首屏加载",{"type":21,"tag":79,"props":609,"children":610},{},[611],{"type":26,"value":590},{"type":21,"tag":52,"props":613,"children":614},{},[615,620,625,630],{"type":21,"tag":79,"props":616,"children":617},{},[618],{"type":26,"value":619},"CSS 代码分割",{"type":21,"tag":79,"props":621,"children":622},{},[623],{"type":26,"value":624},"中",{"type":21,"tag":79,"props":626,"children":627},{},[628],{"type":26,"value":629},"减少样式体积",{"type":21,"tag":79,"props":631,"children":632},{},[633],{"type":26,"value":590},{"type":21,"tag":52,"props":635,"children":636},{},[637,642,646,651],{"type":21,"tag":79,"props":638,"children":639},{},[640],{"type":26,"value":641},"组件懒加载",{"type":21,"tag":79,"props":643,"children":644},{},[645],{"type":26,"value":624},{"type":21,"tag":79,"props":647,"children":648},{},[649],{"type":26,"value":650},"优化首屏速度",{"type":21,"tag":79,"props":652,"children":653},{},[654],{"type":26,"value":624},{"type":21,"tag":52,"props":656,"children":657},{},[658,663,667,672],{"type":21,"tag":79,"props":659,"children":660},{},[661],{"type":26,"value":662},"虚拟列表",{"type":21,"tag":79,"props":664,"children":665},{},[666],{"type":26,"value":580},{"type":21,"tag":79,"props":668,"children":669},{},[670],{"type":26,"value":671},"大幅提升列表性能",{"type":21,"tag":79,"props":673,"children":674},{},[675],{"type":26,"value":624},{"type":21,"tag":52,"props":677,"children":678},{},[679,683,687,692],{"type":21,"tag":79,"props":680,"children":681},{},[682],{"type":26,"value":470},{"type":21,"tag":79,"props":684,"children":685},{},[686],{"type":26,"value":624},{"type":21,"tag":79,"props":688,"children":689},{},[690],{"type":26,"value":691},"减少打包体积",{"type":21,"tag":79,"props":693,"children":694},{},[695],{"type":26,"value":590},{"type":21,"tag":52,"props":697,"children":698},{},[699,704,708,713],{"type":21,"tag":79,"props":700,"children":701},{},[702],{"type":26,"value":703},"运行时优化",{"type":21,"tag":79,"props":705,"children":706},{},[707],{"type":26,"value":624},{"type":21,"tag":79,"props":709,"children":710},{},[711],{"type":26,"value":712},"提升交互响应",{"type":21,"tag":79,"props":714,"children":715},{},[716],{"type":26,"value":580},{"type":21,"tag":52,"props":718,"children":719},{},[720,725,729,734],{"type":21,"tag":79,"props":721,"children":722},{},[723],{"type":26,"value":724},"性能监控",{"type":21,"tag":79,"props":726,"children":727},{},[728],{"type":26,"value":590},{"type":21,"tag":79,"props":730,"children":731},{},[732],{"type":26,"value":733},"持续优化基础",{"type":21,"tag":79,"props":735,"children":736},{},[737],{"type":26,"value":624},{"type":21,"tag":22,"props":739,"children":741},{"id":740},"总结",[742],{"type":26,"value":740},{"type":21,"tag":28,"props":744,"children":745},{},[746],{"type":26,"value":747},"设计系统性能优化的核心策略：",{"type":21,"tag":749,"props":750,"children":751},"ol",{},[752,764,774,784,793],{"type":21,"tag":753,"props":754,"children":755},"li",{},[756,762],{"type":21,"tag":757,"props":758,"children":759},"strong",{},[760],{"type":26,"value":761},"包体积优化",{"type":26,"value":763},"：通过 Tree Shaking、按需导入减少最终打包体积",{"type":21,"tag":753,"props":765,"children":766},{},[767,772],{"type":21,"tag":757,"props":768,"children":769},{},[770],{"type":26,"value":771},"加载优化",{"type":26,"value":773},"：懒加载非关键组件，分割代码按需加载",{"type":21,"tag":753,"props":775,"children":776},{},[777,782],{"type":21,"tag":757,"props":778,"children":779},{},[780],{"type":26,"value":781},"样式优化",{"type":26,"value":783},"：模块化样式、提取关键 CSS、减少运行时计算",{"type":21,"tag":753,"props":785,"children":786},{},[787,791],{"type":21,"tag":757,"props":788,"children":789},{},[790],{"type":26,"value":703},{"type":26,"value":792},"：虚拟化、缓存、事件委托减少计算开销",{"type":21,"tag":753,"props":794,"children":795},{},[796,801],{"type":21,"tag":757,"props":797,"children":798},{},[799],{"type":26,"value":800},"持续监控",{"type":26,"value":802},"：建立性能基准，持续追踪优化效果",{"type":21,"tag":28,"props":804,"children":805},{},[806],{"type":26,"value":807},"通过系统化的性能优化，可以让设计系统在提供丰富功能的同时保持卓越的性能表现。",{"title":7,"searchDepth":809,"depth":809,"links":810},3,[811,813,814,821,826,832,838,843,847,848],{"id":8,"depth":812,"text":8},2,{"id":35,"depth":812,"text":35},{"id":168,"depth":812,"text":171,"children":815},[816,817,818,819,820],{"id":180,"depth":809,"text":180},{"id":195,"depth":809,"text":198},{"id":212,"depth":809,"text":212},{"id":228,"depth":809,"text":228},{"id":242,"depth":809,"text":242},{"id":265,"depth":812,"text":265,"children":822},[823,824,825],{"id":270,"depth":809,"text":270},{"id":284,"depth":809,"text":284},{"id":298,"depth":809,"text":298},{"id":314,"depth":812,"text":317,"children":827},[828,829,830,831],{"id":320,"depth":809,"text":320},{"id":334,"depth":809,"text":337},{"id":351,"depth":809,"text":354},{"id":366,"depth":809,"text":366},{"id":389,"depth":812,"text":389,"children":833},[834,835,836,837],{"id":394,"depth":809,"text":394},{"id":408,"depth":809,"text":408},{"id":422,"depth":809,"text":422},{"id":436,"depth":809,"text":436},{"id":450,"depth":812,"text":450,"children":839},[840,841,842],{"id":455,"depth":809,"text":458},{"id":470,"depth":809,"text":470},{"id":484,"depth":809,"text":484},{"id":500,"depth":812,"text":500,"children":844},[845,846],{"id":505,"depth":809,"text":505},{"id":519,"depth":809,"text":519},{"id":533,"depth":812,"text":533},{"id":740,"depth":812,"text":740},"markdown","content:topics:design:design-system-performance-guide.md","content","topics/design/design-system-performance-guide.md","topics/design/design-system-performance-guide","md",[856,1212,1514],{"_path":857,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":858,"description":859,"keywords":860,"image":866,"author":867,"date":868,"readingTime":869,"topic":5,"body":870,"_type":849,"_id":1209,"_source":851,"_file":1210,"_stem":1211,"_extension":854},"/topics/design/button-component-design","按钮组件设计详解","学习按钮样式、交互状态、无障碍性和最佳实践",[861,862,863,864,865],"按钮设计","Button Component","交互状态","UI 组件","用户体验","/images/topics/button-design.jpg","HTMLPAGE 团队","2025-12-08",18,{"type":18,"children":871,"toc":1191},[872,876,881,886,892,901,907,916,922,931,935,941,952,958,967,973,982,987,996,1001,1012,1017,1026,1031,1043,1078,1089,1132,1137],{"type":21,"tag":22,"props":873,"children":874},{"id":858},[875],{"type":26,"value":858},{"type":21,"tag":28,"props":877,"children":878},{},[879],{"type":26,"value":880},"按钮是 UI 中最重要的交互元素。优秀的按钮设计能够指导用户行为。",{"type":21,"tag":22,"props":882,"children":884},{"id":883},"按钮类型",[885],{"type":26,"value":883},{"type":21,"tag":178,"props":887,"children":889},{"id":888},"primary-button主按钮",[890],{"type":26,"value":891},"Primary Button（主按钮）",{"type":21,"tag":184,"props":893,"children":896},{"className":894,"code":895,"language":341,"meta":7},[343],".btn-primary {\n  background-color: #0066cc;\n  color: #ffffff;\n  padding: 12px 24px;\n  border: none;\n  border-radius: 4px;\n  font-weight: 600;\n  font-size: 16px;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n  background-color: #0052a3;\n  box-shadow: 0 4px 12px rgba(0, 102, 204, 0.2);\n}\n\n.btn-primary:active {\n  background-color: #003d7a;\n  transform: scale(0.98);\n}\n\n.btn-primary:disabled {\n  background-color: #cccccc;\n  cursor: not-allowed;\n  opacity: 0.6;\n}\n",[897],{"type":21,"tag":189,"props":898,"children":899},{"__ignoreMap":7},[900],{"type":26,"value":895},{"type":21,"tag":178,"props":902,"children":904},{"id":903},"secondary-button次按钮",[905],{"type":26,"value":906},"Secondary Button（次按钮）",{"type":21,"tag":184,"props":908,"children":911},{"className":909,"code":910,"language":341,"meta":7},[343],".btn-secondary {\n  background-color: transparent;\n  color: #0066cc;\n  border: 2px solid #0066cc;\n  padding: 10px 22px;\n  border-radius: 4px;\n  font-weight: 600;\n  cursor: pointer;\n  transition: all 0.2s;\n}\n\n.btn-secondary:hover {\n  background-color: rgba(0, 102, 204, 0.1);\n}\n\n.btn-secondary:active {\n  background-color: rgba(0, 102, 204, 0.2);\n}\n",[912],{"type":21,"tag":189,"props":913,"children":914},{"__ignoreMap":7},[915],{"type":26,"value":910},{"type":21,"tag":178,"props":917,"children":919},{"id":918},"danger-button危险按钮",[920],{"type":26,"value":921},"Danger Button（危险按钮）",{"type":21,"tag":184,"props":923,"children":926},{"className":924,"code":925,"language":341,"meta":7},[343],".btn-danger {\n  background-color: #cc0000;\n  color: #ffffff;\n  padding: 12px 24px;\n  border-radius: 4px;\n  cursor: pointer;\n  font-weight: 600;\n}\n\n.btn-danger:hover {\n  background-color: #990000;\n  box-shadow: 0 4px 12px rgba(204, 0, 0, 0.2);\n}\n",[927],{"type":21,"tag":189,"props":928,"children":929},{"__ignoreMap":7},[930],{"type":26,"value":925},{"type":21,"tag":22,"props":932,"children":933},{"id":863},[934],{"type":26,"value":863},{"type":21,"tag":178,"props":936,"children":938},{"id":937},"loading-状态",[939],{"type":26,"value":940},"Loading 状态",{"type":21,"tag":184,"props":942,"children":947},{"className":943,"code":945,"language":946,"meta":7},[944],"language-jsx","import { useState } from 'react';\n\nfunction Button({ children, onClick, loading, ...props }) {\n  const [isLoading, setIsLoading] = useState(false);\n  \n  const handleClick = async () => {\n    setIsLoading(true);\n    try {\n      await onClick();\n    } finally {\n      setIsLoading(false);\n    }\n  };\n  \n  return (\n    \u003Cbutton\n      onClick={handleClick}\n      disabled={isLoading || loading}\n      aria-busy={isLoading || loading}\n      {...props}\n    >\n      {isLoading ? (\n        \u003C>\n          \u003Cspan className=\"spinner\" aria-hidden=\"true\">\u003C/span>\n          {children}\n        \u003C/>\n      ) : (\n        children\n      )}\n    \u003C/button>\n  );\n}\n","jsx",[948],{"type":21,"tag":189,"props":949,"children":950},{"__ignoreMap":7},[951],{"type":26,"value":945},{"type":21,"tag":178,"props":953,"children":955},{"id":954},"disabled-状态",[956],{"type":26,"value":957},"Disabled 状态",{"type":21,"tag":184,"props":959,"children":962},{"className":960,"code":961,"language":341,"meta":7},[343],".btn:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n  background-color: #cccccc;\n  color: #999999;\n}\n\n/* 禁用状态下隐藏指针光标 */\n.btn:disabled:hover {\n  box-shadow: none;\n  transform: none;\n}\n",[963],{"type":21,"tag":189,"props":964,"children":965},{"__ignoreMap":7},[966],{"type":26,"value":961},{"type":21,"tag":178,"props":968,"children":970},{"id":969},"focus-状态",[971],{"type":26,"value":972},"Focus 状态",{"type":21,"tag":184,"props":974,"children":977},{"className":975,"code":976,"language":341,"meta":7},[343],".btn:focus {\n  outline: none;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1),\n              0 0 0 5px #0066cc;\n}\n\n/* 键盘导航焦点 */\n.btn:focus-visible {\n  outline: 2px solid #0066cc;\n  outline-offset: 2px;\n}\n",[978],{"type":21,"tag":189,"props":979,"children":980},{"__ignoreMap":7},[981],{"type":26,"value":976},{"type":21,"tag":22,"props":983,"children":985},{"id":984},"按钮大小",[986],{"type":26,"value":984},{"type":21,"tag":184,"props":988,"children":991},{"className":989,"code":990,"language":341,"meta":7},[343],"/* 小按钮 */\n.btn-sm {\n  padding: 6px 12px;\n  font-size: 12px;\n  min-height: 32px;\n  min-width: 32px;\n}\n\n/* 中等按钮（默认） */\n.btn-md {\n  padding: 12px 24px;\n  font-size: 16px;\n  min-height: 44px;\n  min-width: 44px;\n}\n\n/* 大按钮 */\n.btn-lg {\n  padding: 16px 32px;\n  font-size: 18px;\n  min-height: 56px;\n  min-width: 56px;\n}\n\n/* 全宽按钮 */\n.btn-block {\n  width: 100%;\n  display: block;\n}\n",[992],{"type":21,"tag":189,"props":993,"children":994},{"__ignoreMap":7},[995],{"type":26,"value":990},{"type":21,"tag":22,"props":997,"children":999},{"id":998},"无障碍性",[1000],{"type":26,"value":998},{"type":21,"tag":184,"props":1002,"children":1007},{"className":1003,"code":1005,"language":1006,"meta":7},[1004],"language-html","\u003C!-- 语义正确 -->\n\u003Cbutton type=\"submit\" aria-label=\"提交表单\">\n  提交\n\u003C/button>\n\n\u003C!-- 加载状态 -->\n\u003Cbutton aria-busy=\"true\" disabled>\n  \u003Cspan aria-hidden=\"true\" class=\"spinner\">\u003C/span>\n  加载中...\n\u003C/button>\n\n\u003C!-- 图标按钮 -->\n\u003Cbutton aria-label=\"关闭\">\n  \u003Csvg aria-hidden=\"true\" width=\"24\" height=\"24\">\n    \u003Cline x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n    \u003Cline x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n  \u003C/svg>\n\u003C/button>\n\n\u003C!-- 切换按钮 -->\n\u003Cbutton aria-pressed=\"false\" aria-label=\"点赞\">\n  ♥\n\u003C/button>\n","html",[1008],{"type":21,"tag":189,"props":1009,"children":1010},{"__ignoreMap":7},[1011],{"type":26,"value":1005},{"type":21,"tag":22,"props":1013,"children":1015},{"id":1014},"完整组件示例",[1016],{"type":26,"value":1014},{"type":21,"tag":184,"props":1018,"children":1021},{"className":1019,"code":1020,"language":946,"meta":7},[944],"const Button = React.forwardRef((\n  {\n    children,\n    variant = 'primary',\n    size = 'md',\n    loading = false,\n    disabled = false,\n    icon,\n    className,\n    ...props\n  },\n  ref\n) => {\n  return (\n    \u003Cbutton\n      ref={ref}\n      className={`btn btn-${variant} btn-${size} ${className}`}\n      disabled={disabled || loading}\n      aria-busy={loading}\n      {...props}\n    >\n      {icon && \u003Cspan className=\"btn-icon\" aria-hidden=\"true\">{icon}\u003C/span>}\n      {loading ? (\n        \u003C>\n          \u003Cspan className=\"spinner\" aria-hidden=\"true\">\u003C/span>\n          {children}\n        \u003C/>\n      ) : (\n        children\n      )}\n    \u003C/button>\n  );\n});\n\nButton.displayName = 'Button';\n",[1022],{"type":21,"tag":189,"props":1023,"children":1024},{"__ignoreMap":7},[1025],{"type":26,"value":1020},{"type":21,"tag":22,"props":1027,"children":1029},{"id":1028},"最佳实践",[1030],{"type":26,"value":1028},{"type":21,"tag":28,"props":1032,"children":1033},{},[1034,1036,1041],{"type":26,"value":1035},"✅ ",{"type":21,"tag":757,"props":1037,"children":1038},{},[1039],{"type":26,"value":1040},"应该做的事",{"type":26,"value":1042},":",{"type":21,"tag":1044,"props":1045,"children":1046},"ul",{},[1047,1052,1057,1068,1073],{"type":21,"tag":753,"props":1048,"children":1049},{},[1050],{"type":26,"value":1051},"最小触摸目标 44x44px",{"type":21,"tag":753,"props":1053,"children":1054},{},[1055],{"type":26,"value":1056},"清晰的视觉反馈",{"type":21,"tag":753,"props":1058,"children":1059},{},[1060,1062],{"type":26,"value":1061},"使用语义 HTML ",{"type":21,"tag":189,"props":1063,"children":1065},{"className":1064},[],[1066],{"type":26,"value":1067},"\u003Cbutton>",{"type":21,"tag":753,"props":1069,"children":1070},{},[1071],{"type":26,"value":1072},"提供加载状态反馈",{"type":21,"tag":753,"props":1074,"children":1075},{},[1076],{"type":26,"value":1077},"支持键盘导航",{"type":21,"tag":28,"props":1079,"children":1080},{},[1081,1083,1088],{"type":26,"value":1082},"❌ ",{"type":21,"tag":757,"props":1084,"children":1085},{},[1086],{"type":26,"value":1087},"不应该做的事",{"type":26,"value":1042},{"type":21,"tag":1044,"props":1090,"children":1091},{},[1092,1105,1110,1115,1120],{"type":21,"tag":753,"props":1093,"children":1094},{},[1095,1097,1103],{"type":26,"value":1096},"使用 ",{"type":21,"tag":189,"props":1098,"children":1100},{"className":1099},[],[1101],{"type":26,"value":1102},"\u003Cdiv>",{"type":26,"value":1104}," 模拟按钮",{"type":21,"tag":753,"props":1106,"children":1107},{},[1108],{"type":26,"value":1109},"隐藏焦点指示器",{"type":21,"tag":753,"props":1111,"children":1112},{},[1113],{"type":26,"value":1114},"过多的按钮样式",{"type":21,"tag":753,"props":1116,"children":1117},{},[1118],{"type":26,"value":1119},"忽视禁用状态",{"type":21,"tag":753,"props":1121,"children":1122},{},[1123,1124,1130],{"type":26,"value":1096},{"type":21,"tag":189,"props":1125,"children":1127},{"className":1126},[],[1128],{"type":26,"value":1129},"\u003Ca>",{"type":26,"value":1131}," 代替按钮",{"type":21,"tag":22,"props":1133,"children":1135},{"id":1134},"测试清单",[1136],{"type":26,"value":1134},{"type":21,"tag":1044,"props":1138,"children":1141},{"className":1139},[1140],"contains-task-list",[1142,1155,1164,1173,1182],{"type":21,"tag":753,"props":1143,"children":1146},{"className":1144},[1145],"task-list-item",[1147,1153],{"type":21,"tag":1148,"props":1149,"children":1152},"input",{"disabled":1150,"type":1151},true,"checkbox",[],{"type":26,"value":1154}," 在各种浏览器中测试",{"type":21,"tag":753,"props":1156,"children":1158},{"className":1157},[1145],[1159,1162],{"type":21,"tag":1148,"props":1160,"children":1161},{"disabled":1150,"type":1151},[],{"type":26,"value":1163}," 验证键盘导航",{"type":21,"tag":753,"props":1165,"children":1167},{"className":1166},[1145],[1168,1171],{"type":21,"tag":1148,"props":1169,"children":1170},{"disabled":1150,"type":1151},[],{"type":26,"value":1172}," 检查色彩对比度",{"type":21,"tag":753,"props":1174,"children":1176},{"className":1175},[1145],[1177,1180],{"type":21,"tag":1148,"props":1178,"children":1179},{"disabled":1150,"type":1151},[],{"type":26,"value":1181}," 测试触摸设备",{"type":21,"tag":753,"props":1183,"children":1185},{"className":1184},[1145],[1186,1189],{"type":21,"tag":1148,"props":1187,"children":1188},{"disabled":1150,"type":1151},[],{"type":26,"value":1190}," 屏幕阅读器兼容性",{"title":7,"searchDepth":809,"depth":809,"links":1192},[1193,1194,1199,1204,1205,1206,1207,1208],{"id":858,"depth":812,"text":858},{"id":883,"depth":812,"text":883,"children":1195},[1196,1197,1198],{"id":888,"depth":809,"text":891},{"id":903,"depth":809,"text":906},{"id":918,"depth":809,"text":921},{"id":863,"depth":812,"text":863,"children":1200},[1201,1202,1203],{"id":937,"depth":809,"text":940},{"id":954,"depth":809,"text":957},{"id":969,"depth":809,"text":972},{"id":984,"depth":812,"text":984},{"id":998,"depth":812,"text":998},{"id":1014,"depth":812,"text":1014},{"id":1028,"depth":812,"text":1028},{"id":1134,"depth":812,"text":1134},"content:topics:design:button-component-design.md","topics/design/button-component-design.md","topics/design/button-component-design",{"_path":1213,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1214,"description":1215,"keywords":1216,"image":1221,"author":867,"date":868,"readingTime":1222,"topic":5,"body":1223,"_type":849,"_id":1511,"_source":851,"_file":1512,"_stem":1513,"_extension":854},"/topics/design/dark-mode-design","暗黑模式设计完整方案","学习暗黑模式实现、色彩方案、对比度管理和最佳实践",[1217,1218,1219,1220,865],"暗黑模式","Dark Mode","色彩系统","CSS 变量","/images/topics/dark-mode-design.jpg",20,{"type":18,"children":1224,"toc":1494},[1225,1229,1234,1239,1245,1254,1260,1269,1274,1280,1289,1295,1306,1312,1321,1326,1335,1340,1349,1354,1363,1367,1376,1404,1413,1441,1445],{"type":21,"tag":22,"props":1226,"children":1227},{"id":1214},[1228],{"type":26,"value":1214},{"type":21,"tag":28,"props":1230,"children":1231},{},[1232],{"type":26,"value":1233},"暗黑模式已成为现代应用的标准功能。它能够减少眼睛疲劳、节省电池、改善用户体验。",{"type":21,"tag":22,"props":1235,"children":1237},{"id":1236},"核心色彩系统",[1238],{"type":26,"value":1236},{"type":21,"tag":178,"props":1240,"children":1242},{"id":1241},"light-mode-配色",[1243],{"type":26,"value":1244},"Light Mode 配色",{"type":21,"tag":184,"props":1246,"children":1249},{"className":1247,"code":1248,"language":341,"meta":7},[343],":root {\n  /* Light Mode */\n  --bg-primary: #ffffff;\n  --bg-secondary: #f5f5f5;\n  --bg-tertiary: #efefef;\n  \n  --text-primary: #1a1a1a;\n  --text-secondary: #666666;\n  --text-tertiary: #999999;\n  \n  --border-color: #e0e0e0;\n  --divider-color: #f0f0f0;\n}\n",[1250],{"type":21,"tag":189,"props":1251,"children":1252},{"__ignoreMap":7},[1253],{"type":26,"value":1248},{"type":21,"tag":178,"props":1255,"children":1257},{"id":1256},"dark-mode-配色",[1258],{"type":26,"value":1259},"Dark Mode 配色",{"type":21,"tag":184,"props":1261,"children":1264},{"className":1262,"code":1263,"language":341,"meta":7},[343],"@media (prefers-color-scheme: dark) {\n  :root {\n    /* Dark Mode */\n    --bg-primary: #1a1a1a;\n    --bg-secondary: #2d2d2d;\n    --bg-tertiary: #3a3a3a;\n    \n    --text-primary: #ffffff;\n    --text-secondary: #e0e0e0;\n    --text-tertiary: #a0a0a0;\n    \n    --border-color: #404040;\n    --divider-color: #2a2a2a;\n  }\n}\n",[1265],{"type":21,"tag":189,"props":1266,"children":1267},{"__ignoreMap":7},[1268],{"type":26,"value":1263},{"type":21,"tag":22,"props":1270,"children":1272},{"id":1271},"实现方案",[1273],{"type":26,"value":1271},{"type":21,"tag":178,"props":1275,"children":1277},{"id":1276},"方案-1prefers-color-scheme",[1278],{"type":26,"value":1279},"方案 1：prefers-color-scheme",{"type":21,"tag":184,"props":1281,"children":1284},{"className":1282,"code":1283,"language":341,"meta":7},[343],"/* 自动跟随系统设置 */\n@media (prefers-color-scheme: light) {\n  :root {\n    --bg: #fff;\n    --text: #000;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --bg: #1a1a1a;\n    --text: #fff;\n  }\n}\n\nbody {\n  background: var(--bg);\n  color: var(--text);\n}\n",[1285],{"type":21,"tag":189,"props":1286,"children":1287},{"__ignoreMap":7},[1288],{"type":26,"value":1283},{"type":21,"tag":178,"props":1290,"children":1292},{"id":1291},"方案-2javascript-切换",[1293],{"type":26,"value":1294},"方案 2：JavaScript 切换",{"type":21,"tag":184,"props":1296,"children":1301},{"className":1297,"code":1299,"language":1300,"meta":7},[1298],"language-javascript","// 检测和切换暗黑模式\nfunction initDarkMode() {\n  const isDark = localStorage.getItem('darkMode') === 'true' ||\n                 window.matchMedia('(prefers-color-scheme: dark)').matches;\n  \n  if (isDark) {\n    document.documentElement.setAttribute('data-theme', 'dark');\n  }\n}\n\nfunction toggleDarkMode() {\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n  const newTheme = isDark ? 'light' : 'dark';\n  \n  document.documentElement.setAttribute('data-theme', newTheme);\n  localStorage.setItem('darkMode', newTheme === 'dark');\n}\n\n// CSS 应用\nhtml[data-theme='light'] {\n  color-scheme: light;\n}\n\nhtml[data-theme='dark'] {\n  color-scheme: dark;\n}\n","javascript",[1302],{"type":21,"tag":189,"props":1303,"children":1304},{"__ignoreMap":7},[1305],{"type":26,"value":1299},{"type":21,"tag":178,"props":1307,"children":1309},{"id":1308},"方案-3css-variables-javascript",[1310],{"type":26,"value":1311},"方案 3：CSS Variables + JavaScript",{"type":21,"tag":184,"props":1313,"children":1316},{"className":1314,"code":1315,"language":1300,"meta":7},[1298],"const themes = {\n  light: {\n    '--bg-primary': '#ffffff',\n    '--text-primary': '#000000',\n    '--accent': '#0066cc',\n    '--border': '#e0e0e0',\n  },\n  dark: {\n    '--bg-primary': '#1a1a1a',\n    '--text-primary': '#ffffff',\n    '--accent': '#4da3ff',\n    '--border': '#404040',\n  },\n};\n\nfunction applyTheme(themeName) {\n  const theme = themes[themeName];\n  Object.entries(theme).forEach(([key, value]) => {\n    document.documentElement.style.setProperty(key, value);\n  });\n  localStorage.setItem('theme', themeName);\n}\n",[1317],{"type":21,"tag":189,"props":1318,"children":1319},{"__ignoreMap":7},[1320],{"type":26,"value":1315},{"type":21,"tag":22,"props":1322,"children":1324},{"id":1323},"对比度管理",[1325],{"type":26,"value":1323},{"type":21,"tag":184,"props":1327,"children":1330},{"className":1328,"code":1329,"language":341,"meta":7},[343],"/* Light Mode 对比度 */\n:root {\n  --contrast-high: #000000;     /* 21:1 */\n  --contrast-medium: #333333;   /* 12.6:1 */\n  --contrast-low: #666666;      /* 5.1:1 */\n}\n\n/* Dark Mode 对比度 */\n@media (prefers-color-scheme: dark) {\n  :root {\n    --contrast-high: #ffffff;    /* 21:1 */\n    --contrast-medium: #e0e0e0;  /* 11.6:1 */\n    --contrast-low: #a0a0a0;     /* 4.5:1 */\n  }\n}\n\n/* 应用对比度 */\n.text-primary { color: var(--contrast-high); }\n.text-secondary { color: var(--contrast-medium); }\n.text-tertiary { color: var(--contrast-low); }\n",[1331],{"type":21,"tag":189,"props":1332,"children":1333},{"__ignoreMap":7},[1334],{"type":26,"value":1329},{"type":21,"tag":22,"props":1336,"children":1338},{"id":1337},"图片和图表处理",[1339],{"type":26,"value":1337},{"type":21,"tag":184,"props":1341,"children":1344},{"className":1342,"code":1343,"language":1006,"meta":7},[1004],"\u003C!-- 针对不同主题的图片 -->\n\u003Cpicture>\n  \u003Csource \n    media=\"(prefers-color-scheme: dark)\" \n    srcset=\"chart-dark.svg\"\n  />\n  \u003Cimg src=\"chart-light.svg\" alt=\"图表\" />\n\u003C/picture>\n\n\u003C!-- SVG 颜色适配 -->\n\u003Csvg class=\"icon\">\n  \u003Ccircle cx=\"50\" cy=\"50\" r=\"40\" fill=\"currentColor\" />\n\u003C/svg>\n\n\u003Cstyle>\n  .icon {\n    color: var(--text-primary);\n  }\n\u003C/style>\n",[1345],{"type":21,"tag":189,"props":1346,"children":1347},{"__ignoreMap":7},[1348],{"type":26,"value":1343},{"type":21,"tag":22,"props":1350,"children":1352},{"id":1351},"完整示例",[1353],{"type":26,"value":1351},{"type":21,"tag":184,"props":1355,"children":1358},{"className":1356,"code":1357,"language":946,"meta":7},[944],"import { useState, useEffect } from 'react';\n\nfunction ThemeProvider({ children }) {\n  const [theme, setTheme] = useState('light');\n  const [mounted, setMounted] = useState(false);\n  \n  useEffect(() => {\n    setMounted(true);\n    \n    // 获取保存的主题或系统偏好\n    const savedTheme = localStorage.getItem('theme');\n    const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches \n      ? 'dark' \n      : 'light';\n    \n    const initialTheme = savedTheme || systemTheme;\n    setTheme(initialTheme);\n    document.documentElement.setAttribute('data-theme', initialTheme);\n  }, []);\n  \n  const toggleTheme = () => {\n    const newTheme = theme === 'light' ? 'dark' : 'light';\n    setTheme(newTheme);\n    localStorage.setItem('theme', newTheme);\n    document.documentElement.setAttribute('data-theme', newTheme);\n  };\n  \n  // 防止闪烁\n  if (!mounted) {\n    return null;\n  }\n  \n  return (\n    \u003CThemeContext.Provider value={{ theme, toggleTheme }}>\n      {children}\n      \u003CThemeToggle theme={theme} onChange={toggleTheme} />\n    \u003C/ThemeContext.Provider>\n  );\n}\n\nfunction ThemeToggle({ theme, onChange }) {\n  return (\n    \u003Cbutton \n      onClick={onChange}\n      aria-label={`切换到${theme === 'light' ? '暗黑' : '亮色'}模式`}\n    >\n      {theme === 'light' ? '🌙' : '☀️'}\n    \u003C/button>\n  );\n}\n",[1359],{"type":21,"tag":189,"props":1360,"children":1361},{"__ignoreMap":7},[1362],{"type":26,"value":1357},{"type":21,"tag":22,"props":1364,"children":1365},{"id":1028},[1366],{"type":26,"value":1028},{"type":21,"tag":28,"props":1368,"children":1369},{},[1370,1371,1375],{"type":26,"value":1035},{"type":21,"tag":757,"props":1372,"children":1373},{},[1374],{"type":26,"value":1040},{"type":26,"value":1042},{"type":21,"tag":1044,"props":1377,"children":1378},{},[1379,1384,1389,1394,1399],{"type":21,"tag":753,"props":1380,"children":1381},{},[1382],{"type":26,"value":1383},"支持系统偏好",{"type":21,"tag":753,"props":1385,"children":1386},{},[1387],{"type":26,"value":1388},"提供手动切换选项",{"type":21,"tag":753,"props":1390,"children":1391},{},[1392],{"type":26,"value":1393},"确保足够的对比度",{"type":21,"tag":753,"props":1395,"children":1396},{},[1397],{"type":26,"value":1398},"优化图片和图表",{"type":21,"tag":753,"props":1400,"children":1401},{},[1402],{"type":26,"value":1403},"防止加载闪烁",{"type":21,"tag":28,"props":1405,"children":1406},{},[1407,1408,1412],{"type":26,"value":1082},{"type":21,"tag":757,"props":1409,"children":1410},{},[1411],{"type":26,"value":1087},{"type":26,"value":1042},{"type":21,"tag":1044,"props":1414,"children":1415},{},[1416,1421,1426,1431,1436],{"type":21,"tag":753,"props":1417,"children":1418},{},[1419],{"type":26,"value":1420},"强制单一模式",{"type":21,"tag":753,"props":1422,"children":1423},{},[1424],{"type":26,"value":1425},"忽视性能影响",{"type":21,"tag":753,"props":1427,"children":1428},{},[1429],{"type":26,"value":1430},"使用相同的颜色",{"type":21,"tag":753,"props":1432,"children":1433},{},[1434],{"type":26,"value":1435},"忘记保存用户偏好",{"type":21,"tag":753,"props":1437,"children":1438},{},[1439],{"type":26,"value":1440},"过度使用深色背景",{"type":21,"tag":22,"props":1442,"children":1443},{"id":1134},[1444],{"type":26,"value":1134},{"type":21,"tag":1044,"props":1446,"children":1448},{"className":1447},[1140],[1449,1458,1467,1476,1485],{"type":21,"tag":753,"props":1450,"children":1452},{"className":1451},[1145],[1453,1456],{"type":21,"tag":1148,"props":1454,"children":1455},{"disabled":1150,"type":1151},[],{"type":26,"value":1457}," 在浅色和深色模式下测试所有页面",{"type":21,"tag":753,"props":1459,"children":1461},{"className":1460},[1145],[1462,1465],{"type":21,"tag":1148,"props":1463,"children":1464},{"disabled":1150,"type":1151},[],{"type":26,"value":1466}," 检查颜色对比度符合 WCAG 标准",{"type":21,"tag":753,"props":1468,"children":1470},{"className":1469},[1145],[1471,1474],{"type":21,"tag":1148,"props":1472,"children":1473},{"disabled":1150,"type":1151},[],{"type":26,"value":1475}," 验证图片和图表在两种模式下清晰",{"type":21,"tag":753,"props":1477,"children":1479},{"className":1478},[1145],[1480,1483],{"type":21,"tag":1148,"props":1481,"children":1482},{"disabled":1150,"type":1151},[],{"type":26,"value":1484}," 测试主题切换的平滑性",{"type":21,"tag":753,"props":1486,"children":1488},{"className":1487},[1145],[1489,1492],{"type":21,"tag":1148,"props":1490,"children":1491},{"disabled":1150,"type":1151},[],{"type":26,"value":1493}," 检查用户偏好是否被保存",{"title":7,"searchDepth":809,"depth":809,"links":1495},[1496,1497,1501,1506,1507,1508,1509,1510],{"id":1214,"depth":812,"text":1214},{"id":1236,"depth":812,"text":1236,"children":1498},[1499,1500],{"id":1241,"depth":809,"text":1244},{"id":1256,"depth":809,"text":1259},{"id":1271,"depth":812,"text":1271,"children":1502},[1503,1504,1505],{"id":1276,"depth":809,"text":1279},{"id":1291,"depth":809,"text":1294},{"id":1308,"depth":809,"text":1311},{"id":1323,"depth":812,"text":1323},{"id":1337,"depth":812,"text":1337},{"id":1351,"depth":812,"text":1351},{"id":1028,"depth":812,"text":1028},{"id":1134,"depth":812,"text":1134},"content:topics:design:dark-mode-design.md","topics/design/dark-mode-design.md","topics/design/dark-mode-design",{"_path":1515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1516,"description":1517,"keywords":1518,"image":1523,"author":1524,"date":868,"readingTime":1222,"topic":5,"body":1525,"_type":849,"_id":1790,"_source":851,"_file":1791,"_stem":1792,"_extension":854},"/topics/design/form-controls-design","表单控件设计规范","学习输入框、选择框、复选框等表单控件的设计和实现",[1519,1520,1521,1522,865],"表单设计","Form Controls","输入框","验证反馈","/images/topics/form-controls-design.jpg","AI Content Team",{"type":18,"children":1526,"toc":1776},[1527,1531,1536,1541,1546,1555,1560,1569,1573,1582,1587,1596,1601,1610,1615,1624,1629,1638,1642,1651,1677,1686,1714,1718],{"type":21,"tag":22,"props":1528,"children":1529},{"id":1516},[1530],{"type":26,"value":1516},{"type":21,"tag":28,"props":1532,"children":1533},{},[1534],{"type":26,"value":1535},"优秀的表单设计能够提高用户完成率和满意度。",{"type":21,"tag":22,"props":1537,"children":1539},{"id":1538},"输入框设计",[1540],{"type":26,"value":1538},{"type":21,"tag":178,"props":1542,"children":1544},{"id":1543},"基础文本输入",[1545],{"type":26,"value":1543},{"type":21,"tag":184,"props":1547,"children":1550},{"className":1548,"code":1549,"language":341,"meta":7},[343],".input {\n  width: 100%;\n  padding: 12px 16px;\n  font-size: 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  font-family: inherit;\n  transition: border-color 0.2s;\n}\n\n.input:hover {\n  border-color: #bdbdbd;\n}\n\n.input:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n\n.input:disabled {\n  background-color: #f5f5f5;\n  color: #999999;\n  cursor: not-allowed;\n}\n\n.input.error {\n  border-color: #cc0000;\n}\n\n.input.success {\n  border-color: #00cc00;\n}\n",[1551],{"type":21,"tag":189,"props":1552,"children":1553},{"__ignoreMap":7},[1554],{"type":26,"value":1549},{"type":21,"tag":178,"props":1556,"children":1558},{"id":1557},"标签和提示",[1559],{"type":26,"value":1557},{"type":21,"tag":184,"props":1561,"children":1564},{"className":1562,"code":1563,"language":1006,"meta":7},[1004],"\u003Cdiv class=\"form-group\">\n  \u003Clabel for=\"email\" class=\"form-label\">\n    邮箱地址 \u003Cspan class=\"required\">*\u003C/span>\n  \u003C/label>\n  \u003Cinput\n    id=\"email\"\n    type=\"email\"\n    placeholder=\"user@example.com\"\n    class=\"input\"\n    aria-describedby=\"email-hint\"\n  />\n  \u003Cp id=\"email-hint\" class=\"form-hint\">\n    我们永远不会分享你的邮箱\n  \u003C/p>\n\u003C/div>\n",[1565],{"type":21,"tag":189,"props":1566,"children":1567},{"__ignoreMap":7},[1568],{"type":26,"value":1563},{"type":21,"tag":22,"props":1570,"children":1571},{"id":1522},[1572],{"type":26,"value":1522},{"type":21,"tag":184,"props":1574,"children":1577},{"className":1575,"code":1576,"language":946,"meta":7},[944],"function FormInput({ label, error, success, helperText, value, onChange, ...props }) {\n  return (\n    \u003Cdiv className=\"form-group\">\n      \u003Clabel className=\"form-label\">{label}\u003C/label>\n      \u003Cinput\n        className={`input ${\n          error ? 'error' : success ? 'success' : ''\n        }`}\n        value={value}\n        onChange={onChange}\n        {...props}\n      />\n      {error && (\n        \u003Cp className=\"form-error\" role=\"alert\">\n          {error}\n        \u003C/p>\n      )}\n      {success && (\n        \u003Cp className=\"form-success\">\n          ✓ {success}\n        \u003C/p>\n      )}\n      {helperText && (\n        \u003Cp className=\"form-hint\">{helperText}\u003C/p>\n      )}\n    \u003C/div>\n  );\n}\n",[1578],{"type":21,"tag":189,"props":1579,"children":1580},{"__ignoreMap":7},[1581],{"type":26,"value":1576},{"type":21,"tag":22,"props":1583,"children":1585},{"id":1584},"选择框设计",[1586],{"type":26,"value":1584},{"type":21,"tag":184,"props":1588,"children":1591},{"className":1589,"code":1590,"language":341,"meta":7},[343],".select {\n  appearance: none;\n  width: 100%;\n  padding: 12px 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  background-image: url('data:image/svg+xml;...');\n  background-repeat: no-repeat;\n  background-position: right 12px center;\n  padding-right: 40px;\n  font-size: 16px;\n  cursor: pointer;\n}\n\n.select:hover {\n  border-color: #bdbdbd;\n}\n\n.select:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1592],{"type":21,"tag":189,"props":1593,"children":1594},{"__ignoreMap":7},[1595],{"type":26,"value":1590},{"type":21,"tag":22,"props":1597,"children":1599},{"id":1598},"复选框和单选按钮",[1600],{"type":26,"value":1598},{"type":21,"tag":184,"props":1602,"children":1605},{"className":1603,"code":1604,"language":341,"meta":7},[343],".checkbox-group {\n  display: flex;\n  gap: 12px;\n  align-items: center;\n}\n\n.checkbox-input {\n  width: 20px;\n  height: 20px;\n  cursor: pointer;\n  accent-color: #0066cc;\n}\n\n.checkbox-label {\n  cursor: pointer;\n  user-select: none;\n}\n\n/* 自定义复选框 */\n.custom-checkbox {\n  appearance: none;\n  width: 20px;\n  height: 20px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  cursor: pointer;\n  background-color: white;\n  transition: all 0.2s;\n}\n\n.custom-checkbox:checked {\n  background-color: #0066cc;\n  border-color: #0066cc;\n  background-image: url('data:image/svg+xml;...');\n}\n\n.custom-checkbox:focus {\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1606],{"type":21,"tag":189,"props":1607,"children":1608},{"__ignoreMap":7},[1609],{"type":26,"value":1604},{"type":21,"tag":22,"props":1611,"children":1613},{"id":1612},"文本区域",[1614],{"type":26,"value":1612},{"type":21,"tag":184,"props":1616,"children":1619},{"className":1617,"code":1618,"language":341,"meta":7},[343],".textarea {\n  width: 100%;\n  min-height: 120px;\n  padding: 12px 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  font-family: inherit;\n  font-size: 16px;\n  resize: vertical;\n  transition: border-color 0.2s;\n}\n\n.textarea:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1620],{"type":21,"tag":189,"props":1621,"children":1622},{"__ignoreMap":7},[1623],{"type":26,"value":1618},{"type":21,"tag":22,"props":1625,"children":1627},{"id":1626},"完整表单示例",[1628],{"type":26,"value":1626},{"type":21,"tag":184,"props":1630,"children":1633},{"className":1631,"code":1632,"language":946,"meta":7},[944],"function SignupForm() {\n  const [formData, setFormData] = useState({\n    name: '',\n    email: '',\n    password: '',\n    confirmPassword: '',\n    subscribe: false,\n    terms: false,\n  });\n  \n  const [errors, setErrors] = useState({});\n  const [touched, setTouched] = useState({});\n  const [submitted, setSubmitted] = useState(false);\n  \n  const handleChange = (e) => {\n    const { name, value, type, checked } = e.target;\n    setFormData(prev => ({\n      ...prev,\n      [name]: type === 'checkbox' ? checked : value,\n    }));\n    \n    // 实时验证\n    if (touched[name]) {\n      validateField(name, type === 'checkbox' ? checked : value);\n    }\n  };\n  \n  const handleBlur = (e) => {\n    const { name } = e.target;\n    setTouched(prev => ({ ...prev, [name]: true }));\n    validateField(name, formData[name]);\n  };\n  \n  const validateField = (name, value) => {\n    const newErrors = { ...errors };\n    \n    switch (name) {\n      case 'name':\n        if (!value) newErrors.name = '名字不能为空';\n        else delete newErrors.name;\n        break;\n      case 'email':\n        if (!value) newErrors.email = '邮箱不能为空';\n        else if (!/^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$/.test(value)) {\n          newErrors.email = '请输入有效的邮箱';\n        } else {\n          delete newErrors.email;\n        }\n        break;\n      case 'password':\n        if (!value) newErrors.password = '密码不能为空';\n        else if (value.length \u003C 8) newErrors.password = '密码至少 8 位';\n        else delete newErrors.password;\n        break;\n      case 'confirmPassword':\n        if (value !== formData.password) {\n          newErrors.confirmPassword = '两次密码输入不一致';\n        } else {\n          delete newErrors.confirmPassword;\n        }\n        break;\n      case 'terms':\n        if (!value) newErrors.terms = '必须同意服务条款';\n        else delete newErrors.terms;\n        break;\n      default:\n        break;\n    }\n    \n    setErrors(newErrors);\n  };\n  \n  const validate = () => {\n    const newErrors = {};\n    \n    if (!formData.name) newErrors.name = '名字不能为空';\n    if (!formData.email) newErrors.email = '邮箱不能为空';\n    if (formData.password.length \u003C 8) newErrors.password = '密码至少 8 位';\n    if (formData.password !== formData.confirmPassword) {\n      newErrors.confirmPassword = '两次密码输入不一致';\n    }\n    if (!formData.terms) newErrors.terms = '必须同意服务条款';\n    \n    return newErrors;\n  };\n  \n  const handleSubmit = async (e) => {\n    e.preventDefault();\n    \n    // 标记所有字段已触碰\n    setTouched({\n      name: true,\n      email: true,\n      password: true,\n      confirmPassword: true,\n      terms: true,\n    });\n    \n    const newErrors = validate();\n    \n    if (Object.keys(newErrors).length === 0) {\n      setSubmitted(true);\n      // 提交表单\n      console.log('Form submitted:', formData);\n      // 重置表单\n      setFormData({\n        name: '',\n        email: '',\n        password: '',\n        confirmPassword: '',\n        subscribe: false,\n        terms: false,\n      });\n    } else {\n      setErrors(newErrors);\n    }\n  };\n  \n  return (\n    \u003Cform onSubmit={handleSubmit} noValidate>\n      {submitted && (\n        \u003Cdiv className=\"form-success-message\" role=\"alert\">\n          注册成功！\n        \u003C/div>\n      )}\n      \n      \u003CFormInput\n        label=\"姓名\"\n        name=\"name\"\n        value={formData.name}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.name && errors.name}\n        helperText=\"请输入你的全名\"\n      />\n      \n      \u003CFormInput\n        label=\"邮箱\"\n        name=\"email\"\n        type=\"email\"\n        value={formData.email}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.email && errors.email}\n      />\n      \n      \u003CFormInput\n        label=\"密码\"\n        name=\"password\"\n        type=\"password\"\n        value={formData.password}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.password && errors.password}\n        helperText=\"至少 8 个字符\"\n      />\n      \n      \u003CFormInput\n        label=\"确认密码\"\n        name=\"confirmPassword\"\n        type=\"password\"\n        value={formData.confirmPassword}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.confirmPassword && errors.confirmPassword}\n      />\n      \n      \u003Cdiv className=\"form-group\">\n        \u003Clabel className=\"checkbox-label\">\n          \u003Cinput\n            type=\"checkbox\"\n            name=\"subscribe\"\n            checked={formData.subscribe}\n            onChange={handleChange}\n            className=\"checkbox-input\"\n          />\n          订阅我们的新闻通讯\n        \u003C/label>\n      \u003C/div>\n      \n      \u003Cdiv className=\"form-group\">\n        \u003Clabel className=\"checkbox-label\">\n          \u003Cinput\n            type=\"checkbox\"\n            name=\"terms\"\n            checked={formData.terms}\n            onChange={handleChange}\n            onBlur={handleBlur}\n            className=\"checkbox-input\"\n          />\n          我同意\n          \u003Ca href=\"/terms\" target=\"_blank\" rel=\"noopener noreferrer\">\n            服务条款\n          \u003C/a>\n          和\n          \u003Ca href=\"/privacy\" target=\"_blank\" rel=\"noopener noreferrer\">\n            隐私政策\n          \u003C/a>\n        \u003C/label>\n        {touched.terms && errors.terms && (\n          \u003Cp className=\"form-error\">{errors.terms}\u003C/p>\n        )}\n      \u003C/div>\n      \n      \u003Cbutton type=\"submit\" className=\"btn btn-primary btn-block\">\n        注册\n      \u003C/button>\n    \u003C/form>\n  );\n}\n",[1634],{"type":21,"tag":189,"props":1635,"children":1636},{"__ignoreMap":7},[1637],{"type":26,"value":1632},{"type":21,"tag":22,"props":1639,"children":1640},{"id":1028},[1641],{"type":26,"value":1028},{"type":21,"tag":28,"props":1643,"children":1644},{},[1645,1646,1650],{"type":26,"value":1035},{"type":21,"tag":757,"props":1647,"children":1648},{},[1649],{"type":26,"value":1040},{"type":26,"value":1042},{"type":21,"tag":1044,"props":1652,"children":1653},{},[1654,1659,1664,1669,1673],{"type":21,"tag":753,"props":1655,"children":1656},{},[1657],{"type":26,"value":1658},"使用正确的输入类型",{"type":21,"tag":753,"props":1660,"children":1661},{},[1662],{"type":26,"value":1663},"提供实时验证反馈",{"type":21,"tag":753,"props":1665,"children":1666},{},[1667],{"type":26,"value":1668},"清晰的标签和提示",{"type":21,"tag":753,"props":1670,"children":1671},{},[1672],{"type":26,"value":1051},{"type":21,"tag":753,"props":1674,"children":1675},{},[1676],{"type":26,"value":1077},{"type":21,"tag":28,"props":1678,"children":1679},{},[1680,1681,1685],{"type":26,"value":1082},{"type":21,"tag":757,"props":1682,"children":1683},{},[1684],{"type":26,"value":1087},{"type":26,"value":1042},{"type":21,"tag":1044,"props":1687,"children":1688},{},[1689,1694,1699,1704,1709],{"type":21,"tag":753,"props":1690,"children":1691},{},[1692],{"type":26,"value":1693},"隐藏标签",{"type":21,"tag":753,"props":1695,"children":1696},{},[1697],{"type":26,"value":1698},"过度使用占位符",{"type":21,"tag":753,"props":1700,"children":1701},{},[1702],{"type":26,"value":1703},"验证后立即提交",{"type":21,"tag":753,"props":1705,"children":1706},{},[1707],{"type":26,"value":1708},"忽视无障碍性",{"type":21,"tag":753,"props":1710,"children":1711},{},[1712],{"type":26,"value":1713},"复杂的验证规则",{"type":21,"tag":22,"props":1715,"children":1716},{"id":1134},[1717],{"type":26,"value":1134},{"type":21,"tag":1044,"props":1719,"children":1721},{"className":1720},[1140],[1722,1731,1740,1749,1758,1767],{"type":21,"tag":753,"props":1723,"children":1725},{"className":1724},[1145],[1726,1729],{"type":21,"tag":1148,"props":1727,"children":1728},{"disabled":1150,"type":1151},[],{"type":26,"value":1730}," 所有控件都可用键盘导航",{"type":21,"tag":753,"props":1732,"children":1734},{"className":1733},[1145],[1735,1738],{"type":21,"tag":1148,"props":1736,"children":1737},{"disabled":1150,"type":1151},[],{"type":26,"value":1739}," 标签与输入框关联",{"type":21,"tag":753,"props":1741,"children":1743},{"className":1742},[1145],[1744,1747],{"type":21,"tag":1148,"props":1745,"children":1746},{"disabled":1150,"type":1151},[],{"type":26,"value":1748}," 验证消息清晰",{"type":21,"tag":753,"props":1750,"children":1752},{"className":1751},[1145],[1753,1756],{"type":21,"tag":1148,"props":1754,"children":1755},{"disabled":1150,"type":1151},[],{"type":26,"value":1757}," 色彩对比度足够",{"type":21,"tag":753,"props":1759,"children":1761},{"className":1760},[1145],[1762,1765],{"type":21,"tag":1148,"props":1763,"children":1764},{"disabled":1150,"type":1151},[],{"type":26,"value":1766}," 屏幕阅读器兼容",{"type":21,"tag":753,"props":1768,"children":1770},{"className":1769},[1145],[1771,1774],{"type":21,"tag":1148,"props":1772,"children":1773},{"disabled":1150,"type":1151},[],{"type":26,"value":1775}," 移动设备测试",{"title":7,"searchDepth":809,"depth":809,"links":1777},[1778,1779,1783,1784,1785,1786,1787,1788,1789],{"id":1516,"depth":812,"text":1516},{"id":1538,"depth":812,"text":1538,"children":1780},[1781,1782],{"id":1543,"depth":809,"text":1543},{"id":1557,"depth":809,"text":1557},{"id":1522,"depth":812,"text":1522},{"id":1584,"depth":812,"text":1584},{"id":1598,"depth":812,"text":1598},{"id":1612,"depth":812,"text":1612},{"id":1626,"depth":812,"text":1626},{"id":1028,"depth":812,"text":1028},{"id":1134,"depth":812,"text":1134},"content:topics:design:form-controls-design.md","topics/design/form-controls-design.md","topics/design/form-controls-design",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"image":11,"head":1794,"body":1797,"_type":849,"_id":850,"_source":851,"_file":852,"_stem":853,"_extension":854},{"meta":1795},[1796],{"name":15,"content":16},{"type":18,"children":1798,"toc":2448},[1799,1803,1807,1811,1815,1914,1918,1922,1926,1933,1937,1945,1949,1957,1961,1969,1973,1981,1989,1993,1997,2005,2009,2017,2021,2029,2033,2037,2045,2049,2057,2061,2069,2073,2081,2089,2093,2097,2105,2109,2117,2121,2129,2133,2141,2145,2149,2157,2161,2169,2173,2181,2185,2189,2197,2201,2209,2213,2393,2397,2401,2444],{"type":21,"tag":22,"props":1800,"children":1801},{"id":8},[1802],{"type":26,"value":8},{"type":21,"tag":28,"props":1804,"children":1805},{},[1806],{"type":26,"value":32},{"type":21,"tag":22,"props":1808,"children":1809},{"id":35},[1810],{"type":26,"value":35},{"type":21,"tag":28,"props":1812,"children":1813},{},[1814],{"type":26,"value":42},{"type":21,"tag":44,"props":1816,"children":1817},{},[1818,1836],{"type":21,"tag":48,"props":1819,"children":1820},{},[1821],{"type":21,"tag":52,"props":1822,"children":1823},{},[1824,1828,1832],{"type":21,"tag":56,"props":1825,"children":1826},{},[1827],{"type":26,"value":60},{"type":21,"tag":56,"props":1829,"children":1830},{},[1831],{"type":26,"value":65},{"type":21,"tag":56,"props":1833,"children":1834},{},[1835],{"type":26,"value":70},{"type":21,"tag":72,"props":1837,"children":1838},{},[1839,1854,1869,1884,1899],{"type":21,"tag":52,"props":1840,"children":1841},{},[1842,1846,1850],{"type":21,"tag":79,"props":1843,"children":1844},{},[1845],{"type":26,"value":83},{"type":21,"tag":79,"props":1847,"children":1848},{},[1849],{"type":26,"value":88},{"type":21,"tag":79,"props":1851,"children":1852},{},[1853],{"type":26,"value":93},{"type":21,"tag":52,"props":1855,"children":1856},{},[1857,1861,1865],{"type":21,"tag":79,"props":1858,"children":1859},{},[1860],{"type":26,"value":101},{"type":21,"tag":79,"props":1862,"children":1863},{},[1864],{"type":26,"value":106},{"type":21,"tag":79,"props":1866,"children":1867},{},[1868],{"type":26,"value":111},{"type":21,"tag":52,"props":1870,"children":1871},{},[1872,1876,1880],{"type":21,"tag":79,"props":1873,"children":1874},{},[1875],{"type":26,"value":119},{"type":21,"tag":79,"props":1877,"children":1878},{},[1879],{"type":26,"value":124},{"type":21,"tag":79,"props":1881,"children":1882},{},[1883],{"type":26,"value":129},{"type":21,"tag":52,"props":1885,"children":1886},{},[1887,1891,1895],{"type":21,"tag":79,"props":1888,"children":1889},{},[1890],{"type":26,"value":137},{"type":21,"tag":79,"props":1892,"children":1893},{},[1894],{"type":26,"value":142},{"type":21,"tag":79,"props":1896,"children":1897},{},[1898],{"type":26,"value":147},{"type":21,"tag":52,"props":1900,"children":1901},{},[1902,1906,1910],{"type":21,"tag":79,"props":1903,"children":1904},{},[1905],{"type":26,"value":155},{"type":21,"tag":79,"props":1907,"children":1908},{},[1909],{"type":26,"value":160},{"type":21,"tag":79,"props":1911,"children":1912},{},[1913],{"type":26,"value":165},{"type":21,"tag":22,"props":1915,"children":1916},{"id":168},[1917],{"type":26,"value":171},{"type":21,"tag":28,"props":1919,"children":1920},{},[1921],{"type":26,"value":176},{"type":21,"tag":178,"props":1923,"children":1924},{"id":180},[1925],{"type":26,"value":180},{"type":21,"tag":184,"props":1927,"children":1928},{"code":186},[1929],{"type":21,"tag":189,"props":1930,"children":1931},{"__ignoreMap":7},[1932],{"type":26,"value":186},{"type":21,"tag":178,"props":1934,"children":1935},{"id":195},[1936],{"type":26,"value":198},{"type":21,"tag":184,"props":1938,"children":1940},{"code":201,"language":202,"meta":7,"className":1939},[204],[1941],{"type":21,"tag":189,"props":1942,"children":1943},{"__ignoreMap":7},[1944],{"type":26,"value":201},{"type":21,"tag":178,"props":1946,"children":1947},{"id":212},[1948],{"type":26,"value":212},{"type":21,"tag":184,"props":1950,"children":1952},{"code":217,"language":218,"meta":7,"className":1951},[220],[1953],{"type":21,"tag":189,"props":1954,"children":1955},{"__ignoreMap":7},[1956],{"type":26,"value":217},{"type":21,"tag":178,"props":1958,"children":1959},{"id":228},[1960],{"type":26,"value":228},{"type":21,"tag":184,"props":1962,"children":1964},{"code":233,"language":218,"meta":7,"className":1963},[220],[1965],{"type":21,"tag":189,"props":1966,"children":1967},{"__ignoreMap":7},[1968],{"type":26,"value":233},{"type":21,"tag":178,"props":1970,"children":1971},{"id":242},[1972],{"type":26,"value":242},{"type":21,"tag":184,"props":1974,"children":1976},{"code":247,"language":218,"meta":7,"className":1975},[220],[1977],{"type":21,"tag":189,"props":1978,"children":1979},{"__ignoreMap":7},[1980],{"type":26,"value":247},{"type":21,"tag":184,"props":1982,"children":1984},{"code":256,"language":218,"meta":7,"className":1983},[220],[1985],{"type":21,"tag":189,"props":1986,"children":1987},{"__ignoreMap":7},[1988],{"type":26,"value":256},{"type":21,"tag":22,"props":1990,"children":1991},{"id":265},[1992],{"type":26,"value":265},{"type":21,"tag":178,"props":1994,"children":1995},{"id":270},[1996],{"type":26,"value":270},{"type":21,"tag":184,"props":1998,"children":2000},{"code":275,"language":218,"meta":7,"className":1999},[220],[2001],{"type":21,"tag":189,"props":2002,"children":2003},{"__ignoreMap":7},[2004],{"type":26,"value":275},{"type":21,"tag":178,"props":2006,"children":2007},{"id":284},[2008],{"type":26,"value":284},{"type":21,"tag":184,"props":2010,"children":2012},{"code":289,"language":218,"meta":7,"className":2011},[220],[2013],{"type":21,"tag":189,"props":2014,"children":2015},{"__ignoreMap":7},[2016],{"type":26,"value":289},{"type":21,"tag":178,"props":2018,"children":2019},{"id":298},[2020],{"type":26,"value":298},{"type":21,"tag":184,"props":2022,"children":2024},{"code":303,"language":304,"meta":7,"className":2023},[306],[2025],{"type":21,"tag":189,"props":2026,"children":2027},{"__ignoreMap":7},[2028],{"type":26,"value":303},{"type":21,"tag":22,"props":2030,"children":2031},{"id":314},[2032],{"type":26,"value":317},{"type":21,"tag":178,"props":2034,"children":2035},{"id":320},[2036],{"type":26,"value":320},{"type":21,"tag":184,"props":2038,"children":2040},{"code":325,"language":218,"meta":7,"className":2039},[220],[2041],{"type":21,"tag":189,"props":2042,"children":2043},{"__ignoreMap":7},[2044],{"type":26,"value":325},{"type":21,"tag":178,"props":2046,"children":2047},{"id":334},[2048],{"type":26,"value":337},{"type":21,"tag":184,"props":2050,"children":2052},{"code":340,"language":341,"meta":7,"className":2051},[343],[2053],{"type":21,"tag":189,"props":2054,"children":2055},{"__ignoreMap":7},[2056],{"type":26,"value":340},{"type":21,"tag":178,"props":2058,"children":2059},{"id":351},[2060],{"type":26,"value":354},{"type":21,"tag":184,"props":2062,"children":2064},{"code":357,"language":218,"meta":7,"className":2063},[220],[2065],{"type":21,"tag":189,"props":2066,"children":2067},{"__ignoreMap":7},[2068],{"type":26,"value":357},{"type":21,"tag":178,"props":2070,"children":2071},{"id":366},[2072],{"type":26,"value":366},{"type":21,"tag":184,"props":2074,"children":2076},{"code":371,"language":304,"meta":7,"className":2075},[306],[2077],{"type":21,"tag":189,"props":2078,"children":2079},{"__ignoreMap":7},[2080],{"type":26,"value":371},{"type":21,"tag":184,"props":2082,"children":2084},{"code":380,"language":304,"meta":7,"className":2083},[306],[2085],{"type":21,"tag":189,"props":2086,"children":2087},{"__ignoreMap":7},[2088],{"type":26,"value":380},{"type":21,"tag":22,"props":2090,"children":2091},{"id":389},[2092],{"type":26,"value":389},{"type":21,"tag":178,"props":2094,"children":2095},{"id":394},[2096],{"type":26,"value":394},{"type":21,"tag":184,"props":2098,"children":2100},{"code":399,"language":304,"meta":7,"className":2099},[306],[2101],{"type":21,"tag":189,"props":2102,"children":2103},{"__ignoreMap":7},[2104],{"type":26,"value":399},{"type":21,"tag":178,"props":2106,"children":2107},{"id":408},[2108],{"type":26,"value":408},{"type":21,"tag":184,"props":2110,"children":2112},{"code":413,"language":304,"meta":7,"className":2111},[306],[2113],{"type":21,"tag":189,"props":2114,"children":2115},{"__ignoreMap":7},[2116],{"type":26,"value":413},{"type":21,"tag":178,"props":2118,"children":2119},{"id":422},[2120],{"type":26,"value":422},{"type":21,"tag":184,"props":2122,"children":2124},{"code":427,"language":218,"meta":7,"className":2123},[220],[2125],{"type":21,"tag":189,"props":2126,"children":2127},{"__ignoreMap":7},[2128],{"type":26,"value":427},{"type":21,"tag":178,"props":2130,"children":2131},{"id":436},[2132],{"type":26,"value":436},{"type":21,"tag":184,"props":2134,"children":2136},{"code":441,"language":304,"meta":7,"className":2135},[306],[2137],{"type":21,"tag":189,"props":2138,"children":2139},{"__ignoreMap":7},[2140],{"type":26,"value":441},{"type":21,"tag":22,"props":2142,"children":2143},{"id":450},[2144],{"type":26,"value":450},{"type":21,"tag":178,"props":2146,"children":2147},{"id":455},[2148],{"type":26,"value":458},{"type":21,"tag":184,"props":2150,"children":2152},{"code":461,"language":218,"meta":7,"className":2151},[220],[2153],{"type":21,"tag":189,"props":2154,"children":2155},{"__ignoreMap":7},[2156],{"type":26,"value":461},{"type":21,"tag":178,"props":2158,"children":2159},{"id":470},[2160],{"type":26,"value":470},{"type":21,"tag":184,"props":2162,"children":2164},{"code":475,"language":218,"meta":7,"className":2163},[220],[2165],{"type":21,"tag":189,"props":2166,"children":2167},{"__ignoreMap":7},[2168],{"type":26,"value":475},{"type":21,"tag":178,"props":2170,"children":2171},{"id":484},[2172],{"type":26,"value":484},{"type":21,"tag":184,"props":2174,"children":2176},{"code":489,"language":490,"meta":7,"className":2175},[492],[2177],{"type":21,"tag":189,"props":2178,"children":2179},{"__ignoreMap":7},[2180],{"type":26,"value":489},{"type":21,"tag":22,"props":2182,"children":2183},{"id":500},[2184],{"type":26,"value":500},{"type":21,"tag":178,"props":2186,"children":2187},{"id":505},[2188],{"type":26,"value":505},{"type":21,"tag":184,"props":2190,"children":2192},{"code":510,"language":218,"meta":7,"className":2191},[220],[2193],{"type":21,"tag":189,"props":2194,"children":2195},{"__ignoreMap":7},[2196],{"type":26,"value":510},{"type":21,"tag":178,"props":2198,"children":2199},{"id":519},[2200],{"type":26,"value":519},{"type":21,"tag":184,"props":2202,"children":2204},{"code":524,"language":218,"meta":7,"className":2203},[220],[2205],{"type":21,"tag":189,"props":2206,"children":2207},{"__ignoreMap":7},[2208],{"type":26,"value":524},{"type":21,"tag":22,"props":2210,"children":2211},{"id":533},[2212],{"type":26,"value":533},{"type":21,"tag":44,"props":2214,"children":2215},{},[2216,2238],{"type":21,"tag":48,"props":2217,"children":2218},{},[2219],{"type":21,"tag":52,"props":2220,"children":2221},{},[2222,2226,2230,2234],{"type":21,"tag":56,"props":2223,"children":2224},{},[2225],{"type":26,"value":549},{"type":21,"tag":56,"props":2227,"children":2228},{},[2229],{"type":26,"value":554},{"type":21,"tag":56,"props":2231,"children":2232},{},[2233],{"type":26,"value":559},{"type":21,"tag":56,"props":2235,"children":2236},{},[2237],{"type":26,"value":564},{"type":21,"tag":72,"props":2239,"children":2240},{},[2241,2260,2279,2298,2317,2336,2355,2374],{"type":21,"tag":52,"props":2242,"children":2243},{},[2244,2248,2252,2256],{"type":21,"tag":79,"props":2245,"children":2246},{},[2247],{"type":26,"value":575},{"type":21,"tag":79,"props":2249,"children":2250},{},[2251],{"type":26,"value":580},{"type":21,"tag":79,"props":2253,"children":2254},{},[2255],{"type":26,"value":585},{"type":21,"tag":79,"props":2257,"children":2258},{},[2259],{"type":26,"value":590},{"type":21,"tag":52,"props":2261,"children":2262},{},[2263,2267,2271,2275],{"type":21,"tag":79,"props":2264,"children":2265},{},[2266],{"type":26,"value":598},{"type":21,"tag":79,"props":2268,"children":2269},{},[2270],{"type":26,"value":580},{"type":21,"tag":79,"props":2272,"children":2273},{},[2274],{"type":26,"value":607},{"type":21,"tag":79,"props":2276,"children":2277},{},[2278],{"type":26,"value":590},{"type":21,"tag":52,"props":2280,"children":2281},{},[2282,2286,2290,2294],{"type":21,"tag":79,"props":2283,"children":2284},{},[2285],{"type":26,"value":619},{"type":21,"tag":79,"props":2287,"children":2288},{},[2289],{"type":26,"value":624},{"type":21,"tag":79,"props":2291,"children":2292},{},[2293],{"type":26,"value":629},{"type":21,"tag":79,"props":2295,"children":2296},{},[2297],{"type":26,"value":590},{"type":21,"tag":52,"props":2299,"children":2300},{},[2301,2305,2309,2313],{"type":21,"tag":79,"props":2302,"children":2303},{},[2304],{"type":26,"value":641},{"type":21,"tag":79,"props":2306,"children":2307},{},[2308],{"type":26,"value":624},{"type":21,"tag":79,"props":2310,"children":2311},{},[2312],{"type":26,"value":650},{"type":21,"tag":79,"props":2314,"children":2315},{},[2316],{"type":26,"value":624},{"type":21,"tag":52,"props":2318,"children":2319},{},[2320,2324,2328,2332],{"type":21,"tag":79,"props":2321,"children":2322},{},[2323],{"type":26,"value":662},{"type":21,"tag":79,"props":2325,"children":2326},{},[2327],{"type":26,"value":580},{"type":21,"tag":79,"props":2329,"children":2330},{},[2331],{"type":26,"value":671},{"type":21,"tag":79,"props":2333,"children":2334},{},[2335],{"type":26,"value":624},{"type":21,"tag":52,"props":2337,"children":2338},{},[2339,2343,2347,2351],{"type":21,"tag":79,"props":2340,"children":2341},{},[2342],{"type":26,"value":470},{"type":21,"tag":79,"props":2344,"children":2345},{},[2346],{"type":26,"value":624},{"type":21,"tag":79,"props":2348,"children":2349},{},[2350],{"type":26,"value":691},{"type":21,"tag":79,"props":2352,"children":2353},{},[2354],{"type":26,"value":590},{"type":21,"tag":52,"props":2356,"children":2357},{},[2358,2362,2366,2370],{"type":21,"tag":79,"props":2359,"children":2360},{},[2361],{"type":26,"value":703},{"type":21,"tag":79,"props":2363,"children":2364},{},[2365],{"type":26,"value":624},{"type":21,"tag":79,"props":2367,"children":2368},{},[2369],{"type":26,"value":712},{"type":21,"tag":79,"props":2371,"children":2372},{},[2373],{"type":26,"value":580},{"type":21,"tag":52,"props":2375,"children":2376},{},[2377,2381,2385,2389],{"type":21,"tag":79,"props":2378,"children":2379},{},[2380],{"type":26,"value":724},{"type":21,"tag":79,"props":2382,"children":2383},{},[2384],{"type":26,"value":590},{"type":21,"tag":79,"props":2386,"children":2387},{},[2388],{"type":26,"value":733},{"type":21,"tag":79,"props":2390,"children":2391},{},[2392],{"type":26,"value":624},{"type":21,"tag":22,"props":2394,"children":2395},{"id":740},[2396],{"type":26,"value":740},{"type":21,"tag":28,"props":2398,"children":2399},{},[2400],{"type":26,"value":747},{"type":21,"tag":749,"props":2402,"children":2403},{},[2404,2412,2420,2428,2436],{"type":21,"tag":753,"props":2405,"children":2406},{},[2407,2411],{"type":21,"tag":757,"props":2408,"children":2409},{},[2410],{"type":26,"value":761},{"type":26,"value":763},{"type":21,"tag":753,"props":2413,"children":2414},{},[2415,2419],{"type":21,"tag":757,"props":2416,"children":2417},{},[2418],{"type":26,"value":771},{"type":26,"value":773},{"type":21,"tag":753,"props":2421,"children":2422},{},[2423,2427],{"type":21,"tag":757,"props":2424,"children":2425},{},[2426],{"type":26,"value":781},{"type":26,"value":783},{"type":21,"tag":753,"props":2429,"children":2430},{},[2431,2435],{"type":21,"tag":757,"props":2432,"children":2433},{},[2434],{"type":26,"value":703},{"type":26,"value":792},{"type":21,"tag":753,"props":2437,"children":2438},{},[2439,2443],{"type":21,"tag":757,"props":2440,"children":2441},{},[2442],{"type":26,"value":800},{"type":26,"value":802},{"type":21,"tag":28,"props":2445,"children":2446},{},[2447],{"type":26,"value":807},{"title":7,"searchDepth":809,"depth":809,"links":2449},[2450,2451,2452,2459,2464,2470,2476,2481,2485,2486],{"id":8,"depth":812,"text":8},{"id":35,"depth":812,"text":35},{"id":168,"depth":812,"text":171,"children":2453},[2454,2455,2456,2457,2458],{"id":180,"depth":809,"text":180},{"id":195,"depth":809,"text":198},{"id":212,"depth":809,"text":212},{"id":228,"depth":809,"text":228},{"id":242,"depth":809,"text":242},{"id":265,"depth":812,"text":265,"children":2460},[2461,2462,2463],{"id":270,"depth":809,"text":270},{"id":284,"depth":809,"text":284},{"id":298,"depth":809,"text":298},{"id":314,"depth":812,"text":317,"children":2465},[2466,2467,2468,2469],{"id":320,"depth":809,"text":320},{"id":334,"depth":809,"text":337},{"id":351,"depth":809,"text":354},{"id":366,"depth":809,"text":366},{"id":389,"depth":812,"text":389,"children":2471},[2472,2473,2474,2475],{"id":394,"depth":809,"text":394},{"id":408,"depth":809,"text":408},{"id":422,"depth":809,"text":422},{"id":436,"depth":809,"text":436},{"id":450,"depth":812,"text":450,"children":2477},[2478,2479,2480],{"id":455,"depth":809,"text":458},{"id":470,"depth":809,"text":470},{"id":484,"depth":809,"text":484},{"id":500,"depth":812,"text":500,"children":2482},[2483,2484],{"id":505,"depth":809,"text":505},{"id":519,"depth":809,"text":519},{"id":533,"depth":812,"text":533},{"id":740,"depth":812,"text":740},1778574590876]