vue教程-计算属性(computed) vs 侦听属性(watch) 作者:马育民 • 2022-01-25 23:33 • 阅读:10153 # 本质 ### computed 计算属性 **依赖缓存的派生值**:基于已有数据**计算出新数据**,有缓存,只有依赖变量改变才重新执行函数,模板直接渲染结果。 语法:`key: 函数 / {get, set}` 用途:**数据转换、多数据合并、复杂表达式简化**。 ### watch 侦听器 **数据变化的回调监听**:监听指定变量,变量一变就执行一段逻辑(无返回值,侧重**动作**),无缓存,每次数据更新都会触发。 语法:`key: 处理函数 / {handler, deep, immediate}` 用途:**异步操作、复杂业务逻辑、多步骤操作、深度监听对象/数组**。 # 对比表 | 对比维度 | computed(计算属性) | watch(侦听器) | | --- | --- | --- | | 核心目的 | 得到一个**计算后的值**(供页面渲染) | 数据变化后执行**一段行为/逻辑** | | 缓存机制 | 有缓存;依赖不变,多次访问只算一次 | 无缓存;数据一更新就执行 | | 返回值 | 必须 return 结果,模板可直接插值使用 | 不需要 return,函数内写业务操作 | | 使用场景 | 1. 模板复杂表达式简化 2. 多变量合并计算 3. 简单数据格式化 | 1. 异步请求(接口) 2. 复杂多步逻辑 3. 对象/数组深度监听 4. 数据变更触发DOM、定时器 | | 写法限制 | 不能写异步、复杂副作用逻辑 | 适合写异步、定时器、赋值、请求 | | 初始化执行 | 页面渲染时自动执行一次(计算初始值) | 默认页面初始化不执行,需加 `immediate: true` | | 监听深度 | 只能监听基础依赖,对象内部属性不追踪 | 配置 `deep: true` 可深度监听对象、数组 | | 多依赖 | 天然支持多个依赖变量,任意一个变化就更新 | 一个 watch 只能监听一个目标,多变量需写多个watch | # 使用场景 ### 选择 - **要生成新值、页面渲染用 → 优先 computed** - 简单拼接、四则运算、字符串格式化一律用 computed - **数据变了要做异步、请求、定时器、复杂操作 → 用 watch** - 监听对象内部属性、数组内容变化、初始化就要执行逻辑,用 watch 加 `deep/immediate` ### computed 计算属性适用场景 1. 页面展示需要**组合/加工现有数据** 比如拼接姓名、总价求和、数字格式化、状态文字转换(0=禁用,1=启用)、多条件判断展示标签文本。 2. 简化模板复杂表达式 模板里大量三元、加减、数组过滤,提取成计算属性让页面更简洁。 3. 同一计算结果多处复用 页面多个地方用到同一个加工后的值,有缓存,不会重复计算,性能更好。 4. 需要双向改写派生数据 由多个基础字段合成一个字段,同时支持修改该字段反向拆分更新原数据(get+set)。 ### watch 侦听器适用场景 1. 表单值变化实时 **校验、提示错误**。如:年龄、价格不能是负数,也不能超过最大值;密码复杂度不符合要求;两次密码不一致; 2. 在数据变化时,发送 **ajax请求**。如:百度的输入框的提示;输入验证码,自动向服务器发请求校验是否正确; 3. 数据变动触发副作用逻辑 值改变开启/关闭定时器、弹窗、路由跳转、打印日志、重置表单。 4. 监听对象、数组内部深层修改 修改表单对象里某一个属性、数组新增删除元素后执行逻辑。 5. 页面初始化就要执行一次监听逻辑 进入页面立刻根据当前数据执行一遍业务,不需要等手动修改数据。 6. 单一数据变化触发多步骤复杂流程 一个值改动要连续执行赋值、判断、调用多个方法等一系列操作。 ### 快速区分选用规则 - 目的是**得到一个新值给页面渲染** → computed - 目的是**数据变了去做某一件事** → watch # 易错点 1. computed 内部不要写异步(定时器、axios),缓存机制会失效; 2. watch 监听数组:数组push/splice等方法能触发,但直接赋值对象需要deep; 3. 能用 computed 绝不写 watch,computed 性能更好; 4. computed 依赖必须是响应式数据,普通全局变量不会触发更新。 # 总结 - 计算属性(computed)的函数必须有返回值;侦听属性(watch)不需要 - 计算属性(computed)能实现的功能,侦听属性(watch)都能实现,可能会啰嗦些 - 侦听属性(watch)能实现的功能,计算属性(computed)不一定能实现,可以实现异步 # 侦听属性例子 侦听属性可以实现异步功能(计算属性无法实现),如:延时1秒后执行 ``` <div id="app"> 输入出生年份:<input type="text" v-model="birthday"><br> 年龄:<span>{{age}}</span>(表达式只写监听属性名,会自动调用 监听方法)<br> 年龄:<span>{{age}}</span><br> 年龄:<span>{{age}}</span><br> 年龄:<span>{{age}}</span>(计算属性会缓存结果,如:显示4次年龄,初始化时只执行1次监听方法) </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script> <script> var vm = new Vue({ el: '#app', data:{ birthday:'', age:'' }, watch:{ // 侦听 birthday 属性值变化 birthday:function(newValue,oldValue){ setTimeout(() => { console.log("birthday值从 "+oldValue+" 改为 "+newValue) this.age=new Date().getFullYear() - this.birthday.substr(0,this.birthday.indexOf("-")) }, 1000); } } }) </script> ``` 原文出处:/show_1IX2eveZiMXw.html