前言
基本使用
先看一下以下代码
import {ref, computed } from 'https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.esm-browser.js' let template = ` <table> <tr> <td>单价</td> <td>数量</td> <td>总额</td> </tr> <tr> <td v-on:click='unit_price++'>{{unit_price}}</td> <td v-on:click='quantity++'>{{quantity}}</td> <td>{{total_price}}</td> </tr> </table> ` export default { setup: function () { let unit_price = ref(11) let quantity = ref(90) let total_price = unit_price.value * quantity.value return {unit_price, quantity, total_price} }, template }
如上,我们有两个响应式数据unit_price和quantity,还有一个总价total_price是这两个响应式数据相乘得出来的,在组件挂载时我们能看到total_price的正确结果990,但当我们通过点击unit_price或quantity改变响应式数据时,total_price却未能同步进行更新。
可能你会觉得在模板直接写逻辑不就好了吗,就像
<td>{{unit_price*quantity}}</td>
确实,这样也行,但如果逻辑较多较复杂的情况下,会让模板变得臃肿,难以维护。
因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。
import { ref, computed } from 'https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.esm-browser.js' setup: function () { let unit_price = ref(11) let quantity = ref(90) let total_price = computed(() => unit_price.value * quantity.value) return {unit_price, quantity, total_price} }
这样,无论我们改变unit_price还是quantity,total_price都能侦听到变化进行更新。
Vue 的计算属性会自动追踪响应式依赖。它会检测到
修改计算属性
其实,像上面那样子直接给computed传一个getter函数只能获取到计算属性的值,要想修改计算属性的值,需要给computed传一个对象,这个对象由一个getter函数和一个setter函数组成,通过setter函数我们就可以修改计算属性了。
<tr> <td v-on:click='unit_price++'>{{unit_price}}</td> <td v-on:click='quantity++'>{{quantity}}</td> <td v-on:click='total_price=0'>{{total_price}}</td> </tr> setup: function () { let unit_price = ref(11) let quantity = ref(90) let total_price = computed({ get: () => unit_price.value * quantity.value, set: (newValue) => [unit_price.value, quantity.value] = [newValue, newValue] }) return { unit_price, quantity, total_price } }
当我们单击页面上总价的数值时,就会给total_price赋值为0,然后继续把0赋值给unit_price和quantity,就达到了结果清零的效果。计算属性返回的值是派生状态,更改它是没有意义的,应该更新它所依赖的源状态以触发新的计算。
使用计算属性的注意事项
-
不要改变其他状态、不要在 getter 中做异步请求或者更改 DOM!
-
计算属性描述的是如何根据其他值派生一个值。因此 getter 的职责应该仅为计算和返回该值。