Computed(计算属性)
当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值。
计算函数,复杂的计算都应该放在这里,尽量不要直接在模板语法里面计算,在此处计算的值是会动态变的,即计算的数中有一个值变了,最终结果也会跟着变
我们直接来例子:
// 引用完整版 Vue
import 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里面这样不会让你的代码看着很凌乱,让你的代码的逻辑看着更加的清晰,还有如果修改了里面的值,他会自动发更新结果。
看的不是很明白?
// 引用完整版 Vue
import { 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
}
},
// 如何给三个按钮加事件处理函数
// 使用 computed
template: `
<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(侦听)
用途:用户在数据变化的时候,执行一个函数。
// 引用完整版 Vue
import 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 来计算 displayName
template: `
<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
:如果我们监听一个对象,是否要看对象里面的变化。