Vue3带来了响应式系统的重写基于Proxy替代Object.defineProperty、虚拟DOM的编译优化、以及全新的组合式APIComposition API。组合式API解决了Options API在大型组件中逻辑分散、复用困难的问题让相关逻辑可以聚合在一起并且通过组合函数Composables实现逻辑复用。本文系统讲解组合式API的核心概念、响应式原理、常用API、逻辑复用模式和性能优化技巧。一、为什么需要组合式APIOptions API通过data、methods、computed、watch等选项组织代码简单直观适合小型组件。但在大型组件中同一个功能逻辑的代码会分散在不同选项中数据在data方法在methods侦听器在watch生命周期钩子在mounted等。当组件有几百行代码时理解一个功能需要在不同选项间来回跳转。组合式API允许将相关逻辑聚合在一个setup函数中并且可以抽离为独立的组合函数在多个组件间复用这就是它的核心价值。对比维度Options APIComposition API代码组织按选项类型分散按功能逻辑聚合逻辑复用mixin命名冲突、来源不清晰组合函数明确来源、无冲突TypeScript支持需要vue-class-component原生支持类型推导友好打包体积选项对象全量引入可Tree-shaking按需引入学习曲线低概念简单中需要理解响应式和函数式思维适用场景小型组件、简单页面大型组件、复杂逻辑、逻辑复用二、响应式核心ref与reactiveVue3的响应式系统基于ES6的Proxy实现相比Vue2的Object.definePropertyProxy可以监听对象属性的新增和删除、数组索引和长度变化不需要$set和$delete。组合式API中创建响应式数据有两种方式ref用于基本类型也可以用于对象内部会自动用reactive包裹通过.value访问值reactive用于对象类型直接访问属性即可。ref的优势是可以替换整个对象reactive的优势是不需要.value更直观。script setupimport { ref, reactive, toRefs, computed } from vue// ref基本类型const count ref(0)const name ref(张三)// reactive对象类型const user reactive({name: 李四,age: 25,address: {city: 北京}})// computed计算属性const doubleCount computed(() count.value * 2)// 方法function increment() {count.valueuser.age}// toRefs将reactive对象解构为ref保持响应式const { name: userName, age } toRefs(user)/scripttemplatedivpCount: {{ count }} (double: {{ doubleCount }})/ppUser: {{ user.name }}, {{ user.age }}岁, {{ user.address.city }}/pbutton clickincrement增加/button/div/template需要注意的几个坑第一解构reactive对象会丢失响应式必须用toRefs或toRef转换。第二直接替换reactive对象会丢失响应式因为替换的是变量引用而非Proxy对象这种场景应该用ref。第三ref在模板中会自动解包不需要写.value但在script中必须用.value访问。第四reactive对数组的操作是响应式的包括直接通过索引修改和修改length这是Vue2不具备的能力。三、侦听器watch与watchEffectwatch是惰性的只有在侦听的数据源变化时才执行回调可以获取旧值和新值支持侦听多个数据源。watchEffect是非惰性的立即执行一次自动收集回调中访问到的所有响应式依赖依赖变化时重新执行。watch更适合需要明确知道变化前后值的场景watchEffect更适合需要自动追踪多个依赖的场景。两者都支持通过第二个参数配置immediate、deep、flush等选项。script setupimport { ref, watch, watchEffect } from vueconst count ref(0)const user reactive({ name: 张三, age: 20 })// watch侦听单个refwatch(count, (newVal, oldVal) {console.log(count变化: ${oldVal} - ${newVal})})// watch侦听reactive对象的属性需要用函数返回watch(() user.age, (newVal) {console.log(年龄变化为: ${newVal})})// watch侦听多个数据源watch([count, () user.name], ([newCount, newName], [oldCount, oldName]) {console.log(count: ${oldCount}-${newCount}, name: ${oldName}-${newName})})// watchEffect自动收集依赖立即执行watchEffect(() {console.log(当前count: ${count.value}, 用户: ${user.name})})// 停止侦听const stop watchEffect(() { /* ... */ })stop() // 手动停止/script四、组合函数Composables逻辑复用的正确方式组合函数是组合式API中逻辑复用的核心模式本质上是一个利用Vue响应式API封装有状态逻辑的函数。命名规范上以use开头如useMouse、useFetch、useDebounce。与Vue2的mixin相比组合函数的优势是数据来源明确从函数返回值中解构、不会有命名冲突、TypeScript类型推导友好、可以传递参数实现定制化。VueUse是一个优秀的组合函数工具库提供了数百个常用的组合函数。// composables/useFetch.jsimport { ref, isRef, unref, watchEffect } from vueexport function useFetch(url, options {}) {const data ref(null)const error ref(null)const loading ref(false)async function fetchData() {loading.value trueerror.value nulltry {// unref如果是ref则取.value否则直接返回const res await fetch(unref(url), options)if (!res.ok) throw new Error(HTTP ${res.status})data.value await res.json()} catch (e) {error.value e.message} finally {loading.value false}}// 如果url是refurl变化时自动重新请求if (isRef(url)) {watchEffect(fetchData)} else {fetchData()}return { data, error, loading, refresh: fetchData }}// 在组件中使用script setupimport { ref } from vueimport { useFetch } from ./composables/useFetchconst userId ref(1)const { data, error, loading } useFetch(() /api/user/${userId.value})/script五、生命周期钩子与组件通信组合式API中生命周期钩子通过onXxx函数注册必须在setup同步执行期间调用。对应关系为beforeCreate和created由setup本身替代beforeMount→onBeforeMountmounted→onMountedbeforeUpdate→onBeforeUpdateupdated→onUpdatedbeforeUnmount→onBeforeUnmountunmounted→onUnmounted。组件通信方面props和emits通过defineProps和defineEmits宏声明父组件通过v-bind传递props通过v-on监听事件。跨层级通信使用provide/inject全局状态使用PiniaVue3官方推荐的状态管理库替代Vuex。// 子组件script setupconst props defineProps({title: { type: String, required: true },count: { type: Number, default: 0 }})const emit defineEmits([update, delete])function handleClick() {emit(update, { id: 1, value: hello })}/script// 父组件script setupimport { ref } from vueimport Child from ./Child.vueconst title ref(示例标题)function handleUpdate(payload) {console.log(收到子组件事件:, payload)}/scripttemplateChild :titletitle updatehandleUpdate //template// provide/inject 跨层级通信// 祖先组件import { provide, ref } from vueconst theme ref(dark)provide(theme, theme)// 后代组件import { inject } from vueconst theme inject(theme) // 也可以提供默认值 inject(theme, light)六、性能优化技巧6.1 编译优化静态提升与补丁标记Vue3的编译器在编译模板时会做多种优化静态提升将不包含动态绑定的节点提升到渲染函数之外避免每次渲染重新创建、补丁标记为动态节点添加flagdiff时只比较标记的属性、缓存事件处理函数避免每次渲染创建新函数导致子组件不必要的更新。这些优化是编译器自动完成的开发者无需手动干预但理解原理有助于写出更高效的模板。6.2 合理使用shallowRef与shallowReactive默认的ref和reactive是深度响应式的会递归代理对象的所有嵌套属性。对于大型对象如包含数千项的列表、复杂的第三方库实例深度响应式会带来性能开销。shallowRef和shallowReactive只做浅层响应式只有顶层属性的变化会触发更新嵌套属性的变化不触发。适合用于数据量大但整体替换的场景配合整体赋值来触发更新。import { shallowRef, triggerRef } from vue// shallowRef只有替换整个.value才触发更新const bigList shallowRef([])// 整体替换触发更新bigList.value await fetchBigList()// 如果需要修改内部属性后手动触发bigList.value[0].name 新名称triggerRef(bigList) // 手动触发更新6.3 虚拟列表与组件懒加载渲染大量列表项时即使Vue的虚拟DOM diff很快创建和销毁大量DOM节点仍然会卡顿。虚拟列表Virtual List只渲染可视区域内的DOM节点通过计算滚动位置动态替换内容可以流畅渲染十万级数据。vue-virtual-scroller是常用的虚拟列表库。路由层面使用动态import实现组件懒加载减小首屏打包体积。// 路由懒加载const routes [{path: /dashboard,component: () import(./views/Dashboard.vue)}]// 异步组件 Suspenseimport { defineAsyncComponent, Suspense } from vueconst HeavyComponent defineAsyncComponent(() import(./HeavyComponent.vue))// v-memo缓存模板子树依赖不变时跳过更新div v-memo[item.id, item.name]!-- 只有item.id或item.name变化时才重新渲染这个div --span{{ item.name }}/span/div6.4 避免不必要的响应式不是所有数据都需要响应式。组件内部的常量、不需要在模板中展示的计算中间值、大型静态配置对象都应该用普通变量而非ref/reactive避免不必要的代理开销。可以将常量定义在setup函数外部或者用markRaw标记对象不被代理。结语Vue3组合式API的核心价值是“逻辑聚合”和“逻辑复用”。掌握ref/reactive的响应式原理、watch/watchEffect的侦听机制、组合函数的封装模式就能写出结构清晰、易于维护的Vue3代码。性能优化方面善用shallowRef、虚拟列表、v-memo和组件懒加载可以显著提升大型应用的运行效率。建议在新项目中直接使用script setup语法糖它是组合式API的最佳实践方式代码更简洁编译时优化更充分。
企业数字化 ERP 产品动态
相关推荐
LinuxKit 镜像仓库认证机制深入解析:go-containerregistry `authn` 包实战指南 操作系统云原生容器运行时 【免费下载链接】linuxkit A toolkit for building secure, portable and lean operating systems for containers 项目地址: https://gitcode.com/gh_mirrors/li/linuxkit 点击查看 免费下载 本指南以 linuxkit 仓库中 vendored 的 gith… · 2026/9/27 23:41:53
基于Matlab/Simulink的CDMA仿真系统拆解与误码率分析 简介:基于Matlab与Simulink的CDMA仿真系统源码包,面向电子信息工程、计算机、数学等专业的学习者,用于理解码分多址通信原理、序列生成及扩频解扩流程。资源内同时包含可运行源码与配套仿真数据,适合课程设计、毕业设计或课题研究… · 2026/9/27 23:41:47
网站语言选择避坑指南:5个关键注意事项助你防黑挂马 网站语言选择避坑指南:5个关键注意事项助你防黑挂马 网站被黑挂马,后台突然多出几个陌生的 PHP 文件,浏览器打开全是乱码或赌博链接?别慌,这不仅是技术事故,更是运营灾难。很多甲方对接人在选开发团队时,只盯着价格和功能,却忽略了… · 2026/9/28 0:47:28
别再被拖进度了:行业网站怎么选才不踩坑 别再被拖进度了:行业网站怎么选才不踩坑 改个按钮位置,建站公司说“下周再排期”?改个文案,还要走一遍需求确认流程?这种把简单需求复杂化、把快速响应变成漫长等待的做法,是无数中小企业主和SEO运营人员的噩梦。当你急需上线一个新栏目来抓取“行业… · 2026/9/28 0:47:22
搞懂网站推广的优势,3个对比评测让你流量翻倍 搞懂网站推广的优势,3个对比评测让你流量翻倍 网站被黑挂马不知道怎么办?别慌,先检查你的DNS解析和服务器防火墙日志。很多站长遇到这种情况,第一反应是重装系统,但往往忽略了最基础的 网站推广的优势 布局缺失导致的暴露面过大。… · 2026/9/28 0:47:15
海口网络平台网站开发怎么选:3步避开被拖一周的坑 海口网络平台网站开发怎么选:3步避开被拖一周的坑 改个需求建站公司拖一周,上线前夜服务器被挂满暗链,这种惨痛经历在海口做平台网站开发的朋友身上并不罕见。很多甲方对接人在挑选服务商时,往往只看报价和案例,却忽略了最核心的安全底座。其实,… · 2026/9/28 0:46:27
3个真实案例复盘:电商的网站怎么选不踩坑 3个真实案例复盘:电商的网站怎么选不踩坑 网站做好了没人访问,这是很多老板最头疼的事。花了几万块,界面挺漂亮,结果百度搜不到,客户找不到,钱全打水漂。问题出在哪?往往不是设计不够炫,而是 电商的网站… · 2026/9/28 0:46:15
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
制作网页比较方便的软件怎么选?一文搞懂避坑指南 制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25