AgentSkillsCN

code-optimizer

组件库代码优化器 - 自动检测并修复性能、类型安全、可访问性和包体积问题

中文原作
SKILL.md
--- frontmatter
name: code-optimizer
description: 组件库代码优化器 - 自动检测并修复性能、类型安全、可访问性和包体积问题
license: MIT
compatibility: Requires Vue 3, TypeScript
metadata:
  author: aix
  version: "1.0.0"
  category: quality

Code Optimizer - 组件库代码优化 Skill

自动检测问题并生成修复代码,提升组件质量和性能

优化目标 (4 大核心维度)

维度说明目标自动修复
性能优化v-memo、computed 缓存、虚拟滚动渲染性能提升✅ 支持
类型安全Props/Emits 类型完整、类型导出100% 类型覆盖✅ 支持
可访问性ARIA 属性、键盘导航、焦点管理WCAG 2.1 合规⚠️ 部分
包体积Tree-shaking、按需导入、代码拆分最小化体积✅ 支持

其他规范参考:


1. 性能优化

1.1 v-memo 优化复杂列表

vue
<!-- ❌ 优化前 -->
<template>
  <div v-for="item in items" :key="item.id">
    <div>{{ formatDate(item.date) }}</div>
    <div>{{ formatMoney(item.amount) }}</div>
  </div>
</template>

<!-- ✅ 优化后 -->
<template>
  <div
    v-for="item in formattedItems"
    :key="item.id"
    v-memo="[item.id, item.date, item.amount]"
  >
    <div>{{ item.formattedDate }}</div>
    <div>{{ item.formattedAmount }}</div>
  </div>
</template>

<script setup lang="ts">
const formattedItems = computed(() => {
  return props.items.map(item => ({
    ...item,
    formattedDate: dayjs(item.date).format('YYYY-MM-DD'),
    formattedAmount: `¥${item.amount.toFixed(2)}`,
  }));
});
</script>

1.2 computed 缓存计算结果

typescript
// ❌ 优化前:每次渲染都计算
const classes = () => ['aix-button', `aix-button--${props.type}`];

// ✅ 优化后:computed 缓存
const classes = computed(() => [
  'aix-button',
  `aix-button--${props.type}`,
]);

1.3 防抖/节流事件处理

typescript
// ❌ 优化前
const handleInput = (e: Event) => {
  emit('input', (e.target as HTMLInputElement).value);
};

// ✅ 优化后
import { useDebounceFn } from '@vueuse/core';

const handleInput = useDebounceFn((e: Event) => {
  emit('input', (e.target as HTMLInputElement).value);
}, 300);

1.4 虚拟滚动长列表

vue
<!-- 列表 > 100 项时使用虚拟滚动 -->
<script setup lang="ts">
import { useVirtualList } from '@vueuse/core';

const { list, containerProps, wrapperProps } = useVirtualList(
  props.items,
  { itemHeight: 40 }
);
</script>

<template>
  <div v-bind="containerProps">
    <div v-bind="wrapperProps">
      <div v-for="{ data, index } in list" :key="index">
        {{ data }}
      </div>
    </div>
  </div>
</template>

3. 可访问性优化

3.1 ARIA 属性

vue
<template>
  <div
    role="combobox"
    :aria-expanded="isOpen"
    :aria-haspopup="true"
    :aria-disabled="disabled"
    :aria-activedescendant="activeOptionId"
  >
    <!-- content -->
  </div>
</template>

3.2 键盘导航

typescript
const handleKeydown = (e: KeyboardEvent) => {
  switch (e.key) {
    case 'ArrowDown':
      e.preventDefault();
      focusNext();
      break;
    case 'ArrowUp':
      e.preventDefault();
      focusPrev();
      break;
    case 'Enter':
      e.preventDefault();
      selectCurrent();
      break;
    case 'Escape':
      e.preventDefault();
      close();
      break;
  }
};

3.3 焦点管理

typescript
// Dialog 焦点管理
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap';

const dialogRef = ref<HTMLElement>();
const { activate, deactivate } = useFocusTrap(dialogRef);

watch(() => props.visible, (visible) => {
  if (visible) {
    activate();
  } else {
    deactivate();
  }
});

3.4 无障碍检查清单

  • 所有交互元素有 role 属性
  • aria-expanded/aria-selected 等状态属性
  • 支持键盘导航 (Tab, Enter, Escape, Arrow keys)
  • 焦点管理正确(模态框焦点陷阱)
  • aria-labelaria-labelledby

优化报告模板

code
✅ 组件优化完成!

📊 优化报告 - packages/select

1️⃣ 性能优化
   - ✅ 使用 computed 缓存类名计算
   - ✅ 添加 v-memo 优化列表渲染
   - ⚠️ 建议: 添加虚拟滚动支持

2️⃣ 类型安全
   - ✅ Props 类型完整
   - ✅ Emits 类型完整
   - ✅ 类型已导出

3️⃣ 可访问性
   - ✅ ARIA 属性完整
   - ✅ 键盘导航支持
   - ⚠️ 建议: 添加 aria-describedby

4️⃣ 包体积
   - ✅ Tree-shaking 支持
   - ✅ 无副作用导入
   - 优化前: 15.2 KB
   - 优化后: 12.8 KB (-15.8%)

💡 下一步:
   1. 运行 pnpm type-check
   2. 运行 pnpm test
   3. 运行 pnpm build

自动执行流程

步骤 1: 扫描组件文件

使用 Read 工具读取组件,提取:

  • template 结构
  • script 逻辑
  • style 样式

步骤 2: 检测优化点

code
🔍 扫描优化点...

   📂 packages/select/src/Select.vue

   1️⃣ 性能问题 (3 个):
      ❌ L45: 在模板中直接调用函数 formatOption()
         → 应使用 computed 缓存
      ❌ L78: v-for 列表未使用 v-memo
         → 大列表应添加 v-memo 优化
      ⚠️ L120: 未使用防抖处理输入事件
         → 建议添加 useDebounceFn

   2️⃣ 类型问题 (2 个):
      ❌ L12: Props 接口缺少 JSDoc 注释
      ❌ L89: 使用了类型断言 as SelectOption
         → 应使用类型守卫

   3️⃣ 包体积问题 (1 个):
      ⚠️ package.json 缺少 sideEffects 配置

步骤 3: 自动修复

使用 Edit 工具应用修复:

code
🔧 应用修复...

   ✓ L45: 函数调用 → computed 缓存
   ──────────────────────────────────────
   // 修复前
   <div>{{ formatOption(option) }}</div>

   // 修复后
   <div>{{ formattedOptions[index] }}</div>

   // 添加 computed
   const formattedOptions = computed(() =>
     props.options.map(opt => formatOption(opt))
   );
   ──────────────────────────────────────

   ✓ L78: 添加 v-memo
   ──────────────────────────────────────
   // 修复前
   <div v-for="item in items" :key="item.id">

   // 修复后
   <div
     v-for="item in items"
     :key="item.id"
     v-memo="[item.id, item.selected]"
   >
   ──────────────────────────────────────

   ✓ L12: 添加 JSDoc 注释
   ──────────────────────────────────────
   interface SelectProps {
   + /** 选项列表 */
     options: SelectOption[];
   + /** 当前选中值 */
     modelValue?: string;
   }
   ──────────────────────────────────────

步骤 4: 验证修复

bash
# 自动运行验证
pnpm type-check --filter @aix/select
pnpm lint --filter @aix/select
pnpm test --filter @aix/select

步骤 5: 生成报告

code
✅ 优化完成!

📊 优化报告 - packages/select
─────────────────────────────────────────

1️⃣ 性能优化
   - 检测: 3 个问题
   - 修复: 2 个 ✅
   - 跳过: 1 个 (需手动处理)

2️⃣ 类型安全
   - 检测: 2 个问题
   - 修复: 2 个 ✅

3️⃣ 包体积
   - 检测: 1 个问题
   - 修复: 1 个 ✅
   - 优化前: 15.2 KB
   - 优化后: 12.8 KB (-15.8%)

📈 总体改进:
   - 修复问题: 5/6 (83%)
   - 预计性能提升: ~20%

─────────────────────────────────────────

💡 下一步:
   1. 查看跳过的问题: /code-optimizer --show-skipped
   2. 运行完整测试: pnpm test
   3. 构建验证: pnpm build

自动修复规则

性能优化自动修复

问题检测模式修复方式
模板函数调用{{ func() }}转为 computed
缺少 v-memov-forv-memo添加 v-memo
未防抖输入@input 无防抖包装 useDebounceFn
内联样式计算:style="{ ... }" 含计算提取为 computed

类型安全自动修复

问题检测模式修复方式
缺少 JSDocinterface 属性无注释添加 JSDoc
类型断言as Type提示使用类型守卫
缺少导出类型未在 index.ts 导出添加导出

包体积自动修复

问题检测模式修复方式
缺少 sideEffectspackage.json 无配置添加配置
全量导入import * from转为按需导入
未拆分组件组件 > 500 行提示拆分建议

相关文档