computed和watch
computed
计算属性的意思,它会根据你所以来的数据动态显示新的计算结果。
计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
计算属性的结果会被缓存,只有依赖的响应式property变化才会重新计算。
- 示例
javascript
import Vue from "vue";
Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
id += 1;
return { id: id, name: name, gender: gender };
};
new Vue({
data() {
return {
users: [
createUser("Tom", "male"),
createUser("John", "female"),
createUser("Jack", "male"),
createUser("Gray", "female")
],
gender: ""
};
},
computed:{
displayUsers() {
const hash = {
male: "male",
female: "female"
};
const { users, gender } = this;
if (gender === "") {
return users;
} else if (typeof gender === "string") {
return users.filter(u => u.gender === hash[gender]);
} else {
throw new Error("gender 的值是意外的值");
}
}
},
template: `
<div>
<button @click="gender=''">Show All</button>
<button @click="gender='male'">Male</button>
<button @click="gender='female'">Female</button>
<ul>
<li v-for="(x,index) in displayUsers" :key="index">{{x.name}}-{{x.gender}}</li>
</ul>
</div>
`
}).$mount("#app");
使用目的
因为如果模板中放着很多逻辑式会让模板本身过于笨重,会对页面可维护性造成影响。computed刚好适用于这种情况。
watch
watch的用途是当数据变化时,执行一个函数(watch是异步的)。watch第一次的值是不监听的,一般用于观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。若是要是要监听第一次的值可以使用immediate:true
将立即以表达式的当前值触发回调。
watch有两个选项:
- deep 是否监听对象内的变化
- immediate 是否在第一次渲染执行这个函数
- 示例1
javascript
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 });
}
}
},
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;
const old = last.from;
this.n = old; // watch n 的函数会异步调用
this.$nextTick(() => { //dom更新完后在执行
this.inUndoMode = false;
});
}
}
}).$mount("#app");
- **示例2 **模拟computed,
javascript
new Vue({
data: {
user: {
email: "xxx@qq.com",
nickname: "Tom",
phone: "123456"
},
displayName: ""
},
watch: {
"user.email": {
handler: "changed",
immediate: true // 第一次渲染是也触发 watch
},
"user.nickname": {
handler: "changed",
immediate: true // 第一次渲染是也触发 watch
},
"user.phone": {
handler: "changed",
immediate: true // 第一次渲染是也触发 watch
}
},
// 不如用 computed 来计算 displayName
template: `
<div>
{{displayName}}
<button @click="user.nickname=undefined">remove nickname</button>
</div>
`,
methods: {
changed() {
console.log(arguments);
const user = this.user;
this.displayName = user.nickname || user.email || user.phone;
}
}
}).$mount("#app");
- 示例3
javascript
let vm = new Vue({
data: {
n: 0,
obj: {
a: "a"
}
},
template: `
<div>
{{n}}
<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: {
obj:{
handler: function () {
console.log("obj 变了")
},
deep: true
// deep 属性设定在任何被侦听的对象的property改变时都要执行handler的回调,不论其被嵌套多深
},
"obj.a": function() {
console.log("obj.a 变了");
}
}
}).$mount("#app");
vm.$watch('n',function(){console.log('n出现了')},{immediate:true})
// immediate 属性设定该回调将会在侦听开始之后被立即调用
注意事项
简单类型看值的变化,复杂类型(对象)看地址。
****理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例。
plain
searchQuery: newValue => this.updateAutocomplete(newValue)
this.updateAutocomplete === undefined // true
watch语法
- o1:function(value,oldvalue){},
- o2(){}
- o3:[f1,f2]
- o4:'methodName'
- o5:{handler:fn,deep:true,immediate:true},
'object.a':function(){}
}
- vm.$watch('xxx',fn,{deep:...,immediate:...})
**参考来自 **Vue-文档