computed
-
用途 被计算出来的属性就是计算属性;
-
缓存 1、如果依赖的属性没有变化,就不会重新计算;
2、getter/setter 默认不会做缓存,Vue 做了特殊处理;
- 实例 1、列表展示
new Vue({
data(){
return{
list:[
create('ff','男'),
create('yy','女'),
create('xx','男'),
create('zz','女')
],
gender:''
}
},
computed:{
displayList(){
//computed 的缓存
console.log('displayList 计算了一次')
const hash = {
male:'男',
female:'女'
}
const {list,gender}=this
// if(gender === ''){
// console.log('11')
// return list
// }else if(gender === 'male'){
// return list.filter(u=>u.gender==='男')
// }else if(gender === 'female'){
// return list.filter(u=>u.gender==='女')
// }else{
// throw new Error('搞错了')
// }
//用哈希表简化函数
if(gender === ''){
return list
}else if(typeof gender === 'string'){
return list.filter(u=>u.gender === hash[gender])
}else{
throw new Error('搞错了')
}
}
},
template:`
<div>
<button @click = "gender = '' ">全部</button>
<button @click = "gender = 'male' ">男</button>
<button @click = "gender = 'female' ">女</button>
<ul>
<li v-for='(u,index) in displayList' :key='index'>{{u.name}}-{{u.gender}}</li>
</ul>
</div>
`,
}).$mount('#app')
- 缓存
let obj1 = {
姓: "高",
名: "圆圆",
get 姓名() {
console.log('将姓与名相加')
return this.姓 + this.名;
},
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.slice(1)
},
age: 18
};
console.log(obj1.姓名)
console.log(obj1.姓名)
console.log(obj1.姓名)
console.log('----------------') // 精髓
// 杠精说:为什么每次都要重新计算?如果计算很复杂,不就很浪费时间吗?
// 那就缓存一下吧
// 缓存是啥?就是哈希表
const cache = {} // {'高':{'圆圆': '高圆圆'}}
let obj2 = {
姓: "高",
名: "圆圆",
get 姓名() {
// 由于对象不支持 ['高','圆圆'] 数组作为 key,只能变通一下
if(this.姓 in cache && this.名 in cache[this.姓]){
console.log('有缓存')
return cache[this.姓][this.名]
}
// 如果 cache[this.姓] 不存在,就赋值为 {}
// 如果 cache[this.姓] 存在,就赋值为它自己(相当于什么都不做)
cache[this.姓] = cache[this.姓] || {} // 保底值
cache[this.姓][this.名] = this.姓 + this.名
console.log('将姓与名相加')
return cache[this.姓][this.名];
},
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.slice(1)
},
age: 18
};
console.log(obj2.姓名)
console.log(obj2.姓名)
console.log(obj2.姓名)
watch
watch 是异步的
撤销demo
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
const old = last.from
this.n = old //watch n 的函数会异步调用,使得 this.inUndoMode 一直为 true
this.$nextTick(()=>{
this.inUndoMode = false
})
}
}
}).$mount("#app");
变化
- 简单类型看值,复杂类型(对象)看地址,和 === 规则相同
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 变了:'+this.n)
},
obj(){
//obj 是复杂类型(对象),obj 的值没变,但是地址变了
console.log('obj 变了:'+this.obj)
},
"obj.a":function(){
//obj.a 是对象的值(简单类型),obj.a 的值改变,obj.a 就改变
console.log('obj.a 变了:' + this.obj.a)
},
}
}).$mount("#app");
语法
-
watch:{ 括号里不能用箭头函数,不然 this 不会指向 Vue 实例 }
-
语法一
watch:{
o2: function(value, oldValue){},
o3(){},
o4: [f1, f2],
o5: 'methodName',
o6: {handler:fn, deep:true, immediate:true},
'object.a': function(){}
}
-
语法二
vm.$watch('xxx',fn,{deep: .., immediate: ..})'xxx' 可以改为一个返回字符串的函数 -
immediate 1、在选项参数中指定
immediate: true将立即以表达式的当前值触发回调:
2、注意在带有 immediate 选项时,不能在第一次回调时取消侦听给定的 property;
3、如果你仍然希望在回调内部调用一个取消侦听的函数,应该先检查其函数的可用性:
- deep
为了发现对象内部值的变化,可以在选项参数中指定
deep: true。注意监听数组的变更不需要这么做。 1、如果obj.a 变了,那么 obj 是否也变了?
2、如果需要答案是‘变了’,那么就用 deep:true;
3、如果需要答案是‘没有变’,那么就用默认的 deep:false
computed 和 watch 的区别
- computed 1、computed 计算出一个值,这个值在调用的时候,不需要加括号,可以当属性用;
2、根据依赖会自动缓存,如果依赖不变,computed 的值就不会再重新计算;
- watch 1、watch 用来监听,当数据变化时,执行一个函数;
2、immediate 表示第一次渲染时是否要执行这个函数;
3、deep 表示监听一个对象时,是否要看这个对象里面的属性值的变化。
- 着重点 computed 着重于依赖之间的变化和缓存;watch着重于在变化时执行什么东西,而不是得出一个结果。