[{"data":1,"prerenderedAt":40},["ShallowReactive",2],{"IKjQTnUqVciM_-Da3NxlC8hRy00VXRCuzrQUSqWRFFY":3},[4,16,28],{"title":5,"description":6,"date":7,"tags":8,"readTime":12,"slug":13,"_path":14,"body":15},"Vue 3 Composition API 深入理解","深入探讨 Vue 3 Composition API 的核心概念和最佳实践，包括响应式系统、生命周期钩子和代码组织模式。","2024-07-20",[9,10,11],"Vue3","JavaScript","Frontend","8","vue3-composition-api","/blog/vue3-composition-api","\nVue 3 带来了全新的 Composition API，它为我们提供了更灵活的代码组织方式和更好的 TypeScript 支持。在这篇文章中，我将深入探讨 Composition API 的核心概念和最佳实践。\n\n## 什么是 Composition API\n\nComposition API 是 Vue 3 中引入的一套新的 API，它允许我们以函数的方式组织组件逻辑，而不是像 Options API 那样将逻辑分散在不同的选项中。\n\n### 核心优势\n\n1. **更好的逻辑复用** - 通过组合函数实现逻辑的封装和复用\n2. **更好的 TypeScript 支持** - 函数式的 API 天然支持类型推断\n3. **更灵活的代码组织** - 相关逻辑可以组织在一起\n\n## 响应式系统\n\n### ref 和 reactive\n\n```javascript\nimport { ref, reactive } from 'vue'\n\n// 使用 ref 创建响应式的基本类型\nconst count = ref(0)\n\n// 使用 reactive 创建响应式对象\nconst state = reactive({\n  name: 'Vue 3',\n  version: '3.0'\n})\n```\n\n### 计算属性和侦听器\n\n```javascript\nimport { computed, watch } from 'vue'\n\n// 计算属性\nconst doubled = computed(() => count.value * 2)\n\n// 侦听器\nwatch(count, (newValue, oldValue) => {\n  console.log(`count changed from ${oldValue} to ${newValue}`)\n})\n```\n\n## 生命周期钩子\n\nComposition API 中的生命周期钩子都是以 `on` 开头的函数：\n\n```javascript\nimport { onMounted, onUpdated, onUnmounted } from 'vue'\n\nexport default {\n  setup() {\n    onMounted(() => {\n      console.log('组件已挂载')\n    })\n    \n    onUpdated(() => {\n      console.log('组件已更新')\n    })\n    \n    onUnmounted(() => {\n      console.log('组件将卸载')\n    })\n  }\n}\n```\n\n## 最佳实践\n\n### 1. 逻辑提取和复用\n\n将相关的逻辑提取到自定义的组合函数中：\n\n```javascript\n// composables/useCounter.js\nimport { ref, computed } from 'vue'\n\nexport function useCounter(initialValue = 0) {\n  const count = ref(initialValue)\n  \n  const increment = () => count.value++\n  const decrement = () => count.value--\n  const doubled = computed(() => count.value * 2)\n  \n  return {\n    count,\n    increment,\n    decrement,\n    doubled\n  }\n}\n```\n\n### 2. 组件中使用\n\n```javascript\nimport { useCounter } from '@/composables/useCounter'\n\nexport default {\n  setup() {\n    const { count, increment, decrement, doubled } = useCounter(10)\n    \n    return {\n      count,\n      increment,\n      decrement,\n      doubled\n    }\n  }\n}\n```\n\n## 总结\n\nComposition API 为 Vue 3 带来了更强大和灵活的组件开发体验。通过合理使用 ref、reactive、computed 等 API，我们可以构建出更加模块化和可维护的应用。\n\n记住，Composition API 并不是要完全替代 Options API，而是为了解决复杂组件的逻辑组织问题。在简单组件中，Options API 依然是一个很好的选择。",{"title":17,"description":18,"date":19,"tags":20,"readTime":24,"slug":25,"_path":26,"body":27},"Nuxt 3 性能优化实践","分享在 Nuxt 3 项目中的性能优化经验，包括代码分割、图像优化、缓存策略等实用技巧。","2024-07-15",[21,22,23],"Nuxt3","Performance","SSR","6","nuxt3-performance-optimization","/blog/nuxt3-performance-optimization","\n在现代 Web 开发中，性能优化是至关重要的。本文将分享我在 Nuxt 3 项目中积累的性能优化经验和最佳实践。\n\n## 代码分割和懒加载\n\n### 路由级别的代码分割\n\nNuxt 3 默认会为每个页面进行代码分割，但我们可以进一步优化：\n\n```javascript\n// 使用动态导入进行组件懒加载\nconst LazyComponent = defineAsyncComponent(() => \n  import('~/components/HeavyComponent.vue')\n)\n```\n\n### 条件性加载\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyHeavyComponent v-if=\"showHeavyComponent\" />\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript setup>\nconst LazyHeavyComponent = defineAsyncComponent(() =>\n  import('~/components/HeavyComponent.vue')\n)\n\nconst showHeavyComponent = ref(false)\n\u003C/script>\n```\n\n## 图像优化\n\n### 使用 Nuxt Image 模块\n\n```bash\nnpm install @nuxt/image\n```\n\n```vue\n\u003Ctemplate>\n  \u003CNuxtImg\n    src=\"/images/hero.jpg\"\n    alt=\"Hero image\"\n    width=\"800\"\n    height=\"600\"\n    loading=\"lazy\"\n    format=\"webp\"\n  />\n\u003C/template>\n```\n\n### 响应式图像\n\n```vue\n\u003CNuxtImg\n  src=\"/images/hero.jpg\"\n  sizes=\"sm:100vw md:50vw lg:400px\"\n  alt=\"Responsive hero image\"\n/>\n```\n\n## 缓存策略\n\n### HTTP 缓存头\n\n```javascript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    routeRules: {\n      '/': { prerender: true },\n      '/blog/**': { isr: 60 }, // ISR with 60s revalidation\n      '/api/**': { headers: { 'Cache-Control': 's-maxage=300' } }\n    }\n  }\n})\n```\n\n### 浏览器缓存\n\n```javascript\n// 使用 useFetch 的缓存选项\nconst { data } = await useFetch('/api/posts', {\n  key: 'posts',\n  server: true,\n  default: () => [],\n  transform: (data) => data.posts\n})\n```\n\n## 预加载和预获取\n\n### 关键资源预加载\n\n```vue\n\u003Cscript setup>\nuseHead({\n  link: [\n    {\n      rel: 'preload',\n      href: '/fonts/main.woff2',\n      as: 'font',\n      type: 'font/woff2',\n      crossorigin: 'anonymous'\n    }\n  ]\n})\n\u003C/script>\n```\n\n### 路由预获取\n\n```vue\n\u003CNuxtLink \n  to=\"/blog\" \n  prefetch\n  class=\"nav-link\"\n>\n  技术分享\n\u003C/NuxtLink>\n```\n\n## 构建优化\n\n### Tree Shaking\n\n```javascript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n  build: {\n    transpile: ['@iconify/vue']\n  },\n  \n  // 只导入需要的模块\n  css: [\n    '@/assets/css/main.css'\n  ]\n})\n```\n\n### 压缩和混淆\n\n```javascript\nexport default defineNuxtConfig({\n  nitro: {\n    minify: true,\n    compressPublicAssets: true\n  }\n})\n```\n\n## 运行时优化\n\n### 虚拟滚动\n\n对于长列表，使用虚拟滚动：\n\n```vue\n\u003Cscript setup>\nimport { RecycleScroller } from 'vue-virtual-scroller'\n\nconst items = ref([])\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CRecycleScroller\n    class=\"scroller\"\n    :items=\"items\"\n    :item-size=\"80\"\n    key-field=\"id\"\n    v-slot=\"{ item }\"\n  >\n    \u003Cdiv class=\"item\">\n      {{ item.title }}\n    \u003C/div>\n  \u003C/RecycleScroller>\n\u003C/template>\n```\n\n### 防抖和节流\n\n```javascript\nimport { debounce } from 'lodash-es'\n\nconst searchInput = ref('')\nconst debouncedSearch = debounce((query) => {\n  // 执行搜索\n}, 300)\n\nwatch(searchInput, debouncedSearch)\n```\n\n## 监控和分析\n\n### Web Vitals\n\n```javascript\n// plugins/web-vitals.client.js\nimport { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'\n\nexport default defineNuxtPlugin(() => {\n  getCLS(console.log)\n  getFID(console.log)\n  getFCP(console.log)\n  getLCP(console.log)\n  getTTFB(console.log)\n})\n```\n\n### Bundle 分析\n\n```bash\nnpm run build -- --analyze\n```\n\n## 总结\n\n性能优化是一个持续的过程，需要从多个维度考虑：\n\n1. **代码层面** - 代码分割、懒加载、Tree Shaking\n2. **资源层面** - 图像优化、字体优化、压缩\n3. **缓存层面** - HTTP 缓存、浏览器缓存、CDN\n4. **运行时层面** - 虚拟滚动、防抖节流、内存管理\n\n记住，优化前先测量，优化后再验证。使用 Lighthouse、Chrome DevTools 等工具来指导你的优化工作。",{"title":29,"description":30,"date":31,"tags":32,"readTime":36,"slug":37,"_path":38,"body":39},"TypeScript 泛型进阶指南","深入探讨 TypeScript 泛型的高级用法，包括条件类型、映射类型和实用工具类型的实现原理。","2024-07-10",[33,34,35],"TypeScript","Programming","Advanced","10","typescript-generics-advanced","/blog/typescript-generics-advanced","\nTypeScript 的泛型是其类型系统中最强大的特性之一。本文将深入探讨泛型的高级用法，帮助你写出更加类型安全和灵活的代码。\n\n## 基础泛型回顾\n\n在深入高级用法之前，让我们快速回顾一下基础泛型：\n\n```typescript\n// 基础泛型函数\nfunction identity\u003CT>(arg: T): T {\n  return arg\n}\n\n// 泛型接口\ninterface Container\u003CT> {\n  value: T\n}\n\n// 泛型类\nclass GenericNumber\u003CT> {\n  zeroValue: T\n  add: (x: T, y: T) => T\n}\n```\n\n## 条件类型\n\n条件类型允许我们根据类型关系来选择类型：\n\n```typescript\n// 基础条件类型\ntype IsString\u003CT> = T extends string ? true : false\n\ntype Test1 = IsString\u003Cstring>  // true\ntype Test2 = IsString\u003Cnumber>  // false\n\n// 更复杂的条件类型\ntype NonNullable\u003CT> = T extends null | undefined ? never : T\n\ntype SafeString = NonNullable\u003Cstring | null>  // string\n```\n\n### 分布式条件类型\n\n当条件类型作用于联合类型时，会分布式地应用：\n\n```typescript\ntype ToArray\u003CT> = T extends any ? T[] : never\n\ntype StringOrNumberArray = ToArray\u003Cstring | number>\n// 结果: string[] | number[]\n```\n\n## 映射类型\n\n映射类型允许我们基于旧类型创建新类型：\n\n```typescript\n// 基础映射类型\ntype Readonly\u003CT> = {\n  readonly [P in keyof T]: T[P]\n}\n\ntype Partial\u003CT> = {\n  [P in keyof T]?: T[P]\n}\n\n// 高级映射类型\ntype Getters\u003CT> = {\n  [P in keyof T as `get${Capitalize\u003Cstring & P>}`]: () => T[P]\n}\n\ninterface Person {\n  name: string\n  age: number\n}\n\ntype PersonGetters = Getters\u003CPerson>\n// 结果: { getName: () => string; getAge: () => number }\n```\n\n## 模板字面量类型\n\nTypeScript 4.1 引入了模板字面量类型：\n\n```typescript\ntype EventName\u003CT extends string> = `on${Capitalize\u003CT>}`\n\ntype ClickEvent = EventName\u003C'click'>  // 'onClick'\n\n// 组合使用\ntype AllEventNames\u003CT extends Record\u003Cstring, any>> = {\n  [K in keyof T]: EventName\u003Cstring & K>\n}[keyof T]\n\ninterface Events {\n  click: MouseEvent\n  hover: MouseEvent\n  focus: FocusEvent\n}\n\ntype EventHandlers = AllEventNames\u003CEvents>\n// 'onClick' | 'onHover' | 'onFocus'\n```\n\n## 实用工具类型实现\n\n让我们看看如何实现一些常用的工具类型：\n\n### Pick 和 Omit\n\n```typescript\n// Pick 实现\ntype MyPick\u003CT, K extends keyof T> = {\n  [P in K]: T[P]\n}\n\n// Omit 实现\ntype MyOmit\u003CT, K extends keyof T> = {\n  [P in keyof T as P extends K ? never : P]: T[P]\n}\n\n// 或者使用 Pick 和 Exclude\ntype MyOmit2\u003CT, K extends keyof T> = Pick\u003CT, Exclude\u003Ckeyof T, K>>\n```\n\n### DeepPartial\n\n```typescript\ntype DeepPartial\u003CT> = {\n  [P in keyof T]?: T[P] extends object \n    ? DeepPartial\u003CT[P]> \n    : T[P]\n}\n\ninterface NestedObject {\n  a: {\n    b: {\n      c: string\n    }\n  }\n}\n\ntype PartialNested = DeepPartial\u003CNestedObject>\n// { a?: { b?: { c?: string } } }\n```\n\n### ReturnType 实现\n\n```typescript\ntype MyReturnType\u003CT extends (...args: any) => any> = \n  T extends (...args: any) => infer R ? R : any\n\nfunction example(): string {\n  return 'hello'\n}\n\ntype ExampleReturn = MyReturnType\u003Ctypeof example>  // string\n```\n\n## 高级泛型模式\n\n### 函数重载与泛型\n\n```typescript\nfunction createElement\u003CT extends keyof HTMLElementTagNameMap>(\n  tag: T\n): HTMLElementTagNameMap[T]\nfunction createElement\u003CT extends React.ComponentType\u003Cany>>(\n  component: T\n): React.ReactElement\u003CReact.ComponentProps\u003CT>>\nfunction createElement(tagOrComponent: any) {\n  // 实现\n}\n\n// 使用\nconst div = createElement('div')  // HTMLDivElement\nconst button = createElement('button')  // HTMLButtonElement\n```\n\n### 泛型约束的链式调用\n\n```typescript\nclass QueryBuilder\u003CT = any> {\n  private conditions: string[] = []\n\n  where\u003CK extends keyof T>(\n    field: K, \n    operator: string, \n    value: T[K]\n  ): QueryBuilder\u003CT> {\n    this.conditions.push(`${String(field)} ${operator} ${value}`)\n    return this\n  }\n\n  select\u003CK extends keyof T>(...fields: K[]): QueryBuilder\u003CPick\u003CT, K>> {\n    // 实现选择逻辑\n    return this as any\n  }\n\n  build(): string {\n    return this.conditions.join(' AND ')\n  }\n}\n\n// 使用\ninterface User {\n  id: number\n  name: string\n  email: string\n}\n\nconst query = new QueryBuilder\u003CUser>()\n  .where('name', '=', 'John')\n  .where('id', '>', 0)\n  .select('name', 'email')\n  .build()\n```\n\n## 类型体操实战\n\n### 数组转元组\n\n```typescript\ntype ArrayToTuple\u003CT extends readonly any[]> = T extends readonly [\n  infer First,\n  ...infer Rest\n] \n  ? [First, ...ArrayToTuple\u003CRest>]\n  : []\n\nconst arr = ['a', 'b', 'c'] as const\ntype Tuple = ArrayToTuple\u003Ctypeof arr>  // ['a', 'b', 'c']\n```\n\n### 字符串操作\n\n```typescript\n// 字符串反转\ntype Reverse\u003CS extends string> = S extends `${infer First}${infer Rest}`\n  ? `${Reverse\u003CRest>}${First}`\n  : ''\n\ntype Reversed = Reverse\u003C'hello'>  // 'olleh'\n\n// 驼峰转下划线\ntype CamelToSnake\u003CS extends string> = S extends `${infer T}${infer U}`\n  ? `${T extends Capitalize\u003CT> ? '_' : ''}${Lowercase\u003CT>}${CamelToSnake\u003CU>}`\n  : S\n\ntype SnakeCase = CamelToSnake\u003C'getUserName'>  // 'get_user_name'\n```\n\n## 性能注意事项\n\n### 避免深度递归\n\n```typescript\n// 可能导致性能问题的深度递归\ntype BadDeepObject\u003CT, D extends number = 10> = {\n  [K in keyof T]: D extends 0 \n    ? T[K] \n    : T[K] extends object \n      ? BadDeepObject\u003CT[K], Prev\u003CD>>\n      : T[K]\n}\n\n// 更好的方式：限制递归深度或使用不同的方法\ntype GoodDeepObject\u003CT> = {\n  [K in keyof T]: T[K] extends object \n    ? { [P in keyof T[K]]: T[K][P] }  // 只递归一层\n    : T[K]\n}\n```\n\n## 总结\n\nTypeScript 泛型是一个强大的工具，可以帮助我们：\n\n1. **创建可重用的类型** - 通过泛型参数适应不同的使用场景\n2. **保持类型安全** - 在编译时捕获类型错误\n3. **改善开发体验** - 提供更好的智能提示和重构支持\n\n掌握这些高级泛型技巧，将让你的 TypeScript 代码更加优雅和强大。记住，复杂的类型系统虽然强大，但也要考虑可读性和维护性。",1787195710612]