Vue小记

📅 2026/8/11 21:31:28
Vue小记
目录vue2与vue3生命周期对比OptionsAPI vs CompositionAPIOptionsAPICompositionAPI为什么Composition API要在setup中Composition API多逻辑组织方式nextTick()nextTick()原理nextTick使用场景nextTick使用位置vue2与vue3生命周期对比阶段Vue 2Options APIVue 3Compositions API说明创建前beforeCreate——实例刚创建数据未绑定创建后createdsetup()数据已绑定但 DOM 未挂载挂载前beforeMountonBeforeMount模板编译完成即将挂载挂载后mountedonMountedDOM 已挂载可访问 $el更新前beforeUpdateonBeforeUpdate数据变化DOM 未更新更新后updatedonUpdatedDOM 已更新卸载前beforeDestroyonBeforeUnmount组件即将销毁卸载后destroyedonUnmounted组件已销毁keep-aliveactivated/deactivatedonActivated/onDeactivated缓存组件激活/停用错误捕获errorCapturedonErrorCaptured子组件错误捕获SSR相关——onServerPrefetchSSR 数据预取OptionsAPI vs CompositionAPI对比Options APIComposition API适用版本Vue 2/Vue 3Vue 3专属代码组织按选项类型按逻辑功能逻辑复用mixinsComposable学习曲线低稍高适合场景小型项目中大型项目OptionsAPI在OptionsAPI中使用TypeScript时需要为每个选项属性分别定义类型。例如在data函数中定义的数据需要单独定义类型methods中的方法也需要定义参数和返回值的类型等。这使得类型定义分散在整个组件定义中代码结构相对复杂。export default { // 数据 data() { return { count: 0, name: 张三 } }, // 计算属性 computed: { doubleCount() { return this.count * 2 } }, // 方法 methods: { increment() { this.count } }, // 生命周期 mounted() { console.log(mounted) } }export default { data() { return { count: 0 } }, computed: { double() { return this.count * 2 , methods: { add() { this.count } }, mounted() { console.log(count:, this.count) } }CompositionAPI由于以函数形式组织逻辑在setup函数中可以更方便地进行整体的类型定义。可以对setup函数的输入参数和返回值进行类型定义并且在自定义组合函数中也能很好地定义类型。这种方式与TypeScript的函数类型系统结合得更加紧密代码的类型定义更加简洁清晰。script setup import { ref, computed, onMounted } from vue // 数据 const count ref(0) const name ref(张三) // 计算属性 const doubleCount computed(() count.value * 2) // 方法 function increment() { count.value } // 生命周期 onMounted(() { console.log(mounted) }) /scriptimport { ref, computed, onMounted } from vue export default { setup() { const count ref(0) const double computed(() count.val* 2) function add() { count.value } onMounted(() { console.log(count:, count.value) }) return { count, double, add } } }核心优势特性说明逻辑复用通过useXxx()组合函数轻松复用逻辑代码组织相关逻辑集中利于大型项目维护类型推断更好的ts支持更小体积更灵活的tree-shaking,减小包体积逻辑复用示例// useCount.js export function useCount() { const count ref(0) function add() { count.value } return { count, add } } // 组件中使用 const { count, add } useCount()为什么Composition API要在setup中Composition API必须在setup阶段调用。Vue 3 的 Composition API 本质上是一组 函数 API ref 、 reactive 、 onMounted 等它们的设计原理是在组件创建阶段setup同步调用返回响应式数据或注册生命周期回调。setup是VUE3的入口点组件实例创建 ↓ setup() 执行 ← Composition API 在这里生效 ↓ template 编译 / DOM 渲染 ↓ onMounted() 执行Vue 2 的 data 、 methods 、 computed 是分散在各个选项中由 Vue 内部在适当时机调用。Vue 3 统一改为 setup() 入口所有逻辑在里面通过函数调用注册。script setup 是 setup() 的 语法糖 让代码更简洁普通写法export default { setup() { const count ref(0) function increment() { count.value } onMounted(() { console.log(mounted) }) return { count, increment } } }script setup写法script setup const count ref(0) function increment() { count.value } onMounted(() { console.log(mounted) }) // 无需 return模板直接用 count、increment /script图解流程普通 setup(): ┌─────────────────────────────────┐ │ setup() { │ │ const count ref(0) ← 注册响应式 │ onMounted(...) ← 注册生命周期回调 │ return { count } ← 暴露给模板 │ } │ └────────────────────────────────── script setup: ┌───────────────────────────────── │ script setup │ │ const count ref(0) ← 注册响应式编译器自动处理 │ onMounted(...) ← 注册生命周期编译器自动处理 │ // 无需 return ← 编译器自动暴露给模板 │ /script │ └─────────────────────────────────┘问题答案为什么在 setup 中setup 是 Vue 3 的初始化入口Composition API 函数需要在组件创建时同步调script setup 是什么etup 的语法糖省去 return 语句编译器自动处理暴露逻辑可以不用吗Vue 3 仍支持 Options API但 Composition API 是未来趋势Composition API多逻辑组织方式核心思想按功能分组使用Composables(组合函数)方式一使用Composables(推荐)把相关逻辑抽离到独立的组合函数文件中src/ composables/ useCount.js # 计数相关 useSearch.js # 搜索相关逻辑 useAuth.js # 认证相关逻辑useCount.jsimport { ref, computed } from vue export function useCount() { const count ref(0) const double computed(() count.value * 2) function increment() { count.value } function reset() { count.value 0 } return { count, double, increment, reset } }useSearch.jsimport { ref } from vue export function useSearch() { const keyword ref() const results ref([]) async function search() { // 搜索逻辑 } return { keyword, results, search } }组件中使用script setup import { useCount } from /composables/useCount import { useSearch } from /composables/useSearch / 按逻辑分组互不影响 const { count, double, increment } useCount() const { keyword, results, search } useSearch() /script方式二在setup中按功能分区script setup import { ref, computed, onMounted,onUnmounted } from vue // 1. 用户相关逻辑 const userName ref() const userInfo ref({}) function fetchUser() { /* ... */ } // 2. 分页相关逻辑 const page ref(1) const pageSize ref(10) const total ref(0) function nextPage() { page.value } function prevPage() { page.value-- } // 3. 弹窗相关逻辑 const visible ref(false) function openModal() { visible.value true } function closeModal() { visible.value false } // 生命周期 onMounted(() { fetchUser() }) onUnmounted(() { /* 清理 */ }) /script场景推荐方式逻辑需复用Composables useXxx.js 逻辑不复杂不复用setup 内分区注释nextTick()Vue的DOM更新是异步的不会立即生效多个数据变化会合并成一次DOM更新提高性能nextTick用于在DOM更新完成后执行回调。流程图数据变化 → 触发更新 → 加入更新队列 → nextTick → 执行回调 → DOM 已更新 ↑ ↓ | | └── 同步代码继续执行 回调函数中获取到最新 DOMnextTick()原理Promise队列机制Vue3内部维护一个callbacks(回调队列)存放nextTick的回调函数由microtask执行callbacksmicrotaskVue内部维护的数组存放所有nextTick的回调js执行机制(任务队列)存储待执行的函数执行这些函数的时机/方式依赖microtask执行提供执行能力Vue用microtask来异步执行callbacks中的回调比setTimeOut更快保证在DOM更新后第一时间执行nextTick使用场景需要等Vue更新完DOM后再执行操作时就用nextTickVue数据变化-DOM更新是异步的-需要nextTick当需要确保DOM已经更新时当需要访问组件引用或DOM元素时当需要在数据变更后执行依赖DOM操作时nextTick使用位置位置可用说明setup()是数据响应式已建立但DOM未渲染onMounted()是DOM挂载完成等待子组件渲染onUpdated()是DOM更新后需等待本次更新完成methods是最常见数据变化后操作DOMwatch是响应数据变化执行DOM操作computed否不推荐computed是同步的beforeCreate否setup()之前响应式未建立场景对应位置场景推荐位置数据变化后获取DOMmethods或watch组件挂载后初始化onMounted组件更新后操作DOMonMounted异步操作后获取DOMasync/awaitnextTickrouter路由是URL路径到组件的映射(如/home-Home组件)router-view vs router-linkrouter-view:用于渲染路由出口渲染匹配到的组件(根据URL在router-view中显示对应组件)。当一个路由被匹配时它的组件将会渲染在 router-view 中。可以不需要router-link,URL变化时自动渲染对应组件。router-link:用于跳转url路径发生变化导航链接点击切换路由(默认渲染为a),可以将某个链接或者按钮转换成一个具有路由功能的链接。可以不需要router-view,单纯做导航触发。二者可以组合使用也可以分开使用。行为含义跳转URL 路径发生变化如 /home → /about 渲染根据 URL 在 router-view 中显示对应组件只有跳转到内部组件才使用router-view渲染URL 变化 │ ├── http://xxx ──→ 外部链接 ──→ 浏览器跳转整个页面卸载 │ └── /about ──→ Vue Router 处理 │ ├── 路由表有匹配 ──→ router-view 渲染对应组件 │ └── 路由表无匹配 ──→ 渲染 404路由跳转的两种方式方式代码组件式router-link to/home首页/router-linkJS 编程式router.push(/home)