Computed(计算属性)
当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值。
计算函数,复杂的计算都应该放在这里,尽量不要直接在模板语法里面计算,在此处计算的值是会动态变的,即计算的数中有一个值变了,最终结果也会跟着变
我们直接来例子:
// 引用完整版 Vueimport Vue from "vue/dist/vue.js";Vue.config.productionTip = false;new Vue({data() {return {num1: 10,num2: 20,nums: 5};},computed: {addNum: {get() {return Number(this.nums) + Number(this.num1) + Number(this.num2);},set(value) {console.log(value);}}},template: `<div>// 这里就是计算出来的addNum{{addNum}}</div></div>`,methods: {}}).$mount("#app");
上面代码就用到了computed。如果有很大的计算量的代码。就可以放在computed里面这样不会让你的代码看着很凌乱,让你的代码的逻辑看着更加的清晰,还有如果修改了里面的值,他会自动发更新结果。
看的不是很明白?
// 引用完整版 Vueimport { has } from "core-js/core/dict";import Vue from "vue/dist/vue.js";Vue.config.productionTip = false;let id = 0;const createUser = (name, gender) => {id += 1;return { id, name, gender };};new Vue({data() {return {users: [createUser("方方", "男"),createUser("圆圆", "女"),createUser("小新", "男"),createUser("小葵", "女")],gender:""};},computed:{displayUsers(){const hash = {male:'男',female: '女'}const {users ,gender}= this;if (gender === '') {return this.users}else if (typeof gender === string){return this.users.filter(u=>u.gender === hash[gender]);}}},methods:{setGender(string){this.gender = string}},// 如何给三个按钮加事件处理函数// 使用 computedtemplate: `<div><div><button @click="setGender('')">全部</button><button @click="setGender('male')">男</button><button @click="setGender('female')">女</button></div><ul><li v-for="u in displayUsers" :key="u.id">{{u.name}} - {{u.gender}}</li></ul></div>`}).$mount("#app");
这里的computed就是一个稍微大一点的计算量了。可以看到,我们在里面有个对于性别的判断。获取性别后就会去过滤,是的在点击按钮时出现相同性别的信息。
注意
computed是有缓存的,也就是,如果依赖的属性没有变化,技术属性就不会在算一次。
我们看上面的例子。如我们点击全部,男,女。都会进行计算,但是如果我们连续的点击单独的一个按钮,他不会每次都计算,只会计算一次。
getter I setter默认不会做缓存,Vue 做了特殊处理。
Watch(侦听)
用途:用户在数据变化的时候,执行一个函数。
// 引用完整版 Vueimport Vue from "vue/dist/vue.js";Vue.config.productionTip = false;new Vue({data: {n: 0,history: [],inUndoMode: false},watch: {n: function(newValue, oldValue) {console.log(this.inUndoMode);if (!this.inUndoMode) {this.history.push({ from: oldValue, to: newValue });}}},// 不如用 computed 来计算 displayNametemplate: `<div>{{n}}<hr /><button @click="add1">+1</button><button @click="add2">+2</button><button @click="minus1">-1</button><button @click="minus2">-2</button><hr/><button @click="undo">撤销</button><hr/>{{history}}</div>`,methods: {add1() {this.n += 1;},add2() {this.n += 2;},minus1() {this.n -= 1;},minus2() {this.n -= 2;},undo() {const last = this.history.pop();this.inUndoMode = true;console.log("ha" + this.inUndoMode);const old = last.from;this.n = old; // watch n 的函数会异步调用this.$nextTick(() => {this.inUndoMode = false;});}}}).$mount("#app");
整个代码就实现了,当我们对一个数进行加减时,watch会侦听这个动作,然后记录下来。

同时watch还能模拟computed。代码示例。
什么是变化
我们直接看代码
// 引用完整版 Vue,方便讲解import Vue from "vue/dist/vue.js";Vue.config.productionTip = false;new Vue({data: {n: 0,obj: {a: "a"}},template: `<div><button @click="n += 1">n+1</button><button @click="obj.a += 'hi'">obj.a + 'hi'</button><button @click="obj = {a:'a'}">obj = 新对象</button></div>`,watch: {n() {console.log("n 变了");},obj() {console.log("obj 变了");},"obj.a": function() {console.log("obj.a 变了");}}}).$mount("#app");
这个代码实现的功能是:当我们点击按钮可以观察谁真正的变动了,例如我们点击了第一个按钮就会出现如下:

显示 n 变了。
这里得出结论:
- 如果把简单的数据类型变了 也就是上面的
n += 1那么他就是变化了。 - 如果把对象里面的一个属性的值变了。也就是
obj.a += 'hi。对象里面的值变了,但是对象是没有变的,原因就是对象存的是一个固定的地址。 - 如果地址改了那么对象才会变化。
如果我们想要对象里面的值obj.a变动了告诉对象obj你也变化了.
就可以用 deep:true
watch: {n() {console.log("n 变了");},obj: {handler(){console.log("obj 变了");},deep:true},}
那么我们得出:
如果obj.a变了,请问obj算不算也变了
- 如果你需要答案是「也变了」
那么就用deep : true - 如果你需要答案是「没有变」
那么就用deep:false - deep的意思是,监听object的时候是否往深了看
watch后面不能用箭头函数,this会指向全局对象
computed 和 watch 的区别
computed就是计算属性。
computed就是计算一个属性的,调用他的时候不需要加括号。
二是,他会根据依赖自动缓存功能,如果依赖不变,他就不会去重新计算。
watch就是监听、侦听。
如果一个属性变化了我们就去执行一个函数。
支持异步的
watch有2个选项。
- 1个是
immediate:表示 是否在第一次渲染的时候执行函数。 - 2个是
deep:如果我们监听一个对象,是否要看对象里面的变化。
