计算属性 computed
不需要加括号
会根据依赖是否变化来缓存watch 侦听
一旦data发生变化,就执行的函数
options.watch用法
this.$watch用法
deep,immediate含义
data 变化的时候除了更新UI 还能做点啥?
计算属性 computed
用途:
被计算出来的属性就是计算属性
需求1 div中展示用户的名字,点击会更set
new Vue({
data: {
user: {
email: "fangyinghang@qq.com",
nickname: "方方",
phone: "13812312312"
}
},
template: `
<div>//没有名称就展示email,再没有就展示phone
{{user.nickname || user.email || user.phone}}
<div>
//但是我可能多个地方展示,难道要一直复制这一堆吗?
{{user.nickname || user.email || user.phone}}
</div>
</div>
`
}).$mount("#app");
如果有一天要优先展示phone 那要把每个地方都改掉?
使用计算属性computed 来计算 displayName
computed
computed: {
// displayName() {两种写法 函数写法和对象写法
// const user = this.user;
// return user.nickname || user.email || user.phone;
// }
displayName:{
get(){
const user = this.user;
return user.nickname || user.email || user.phone;
},
set(value){
this.user.nickname = value
}
}
},
template: `
<div>
{{displayName}}
<div>
{{displayName}}
<button @click = "add"></button>
</div>
</div>
`,
methods: {
add() {
console.log("add");
this.displayName = "圆圆"; //set的使用
}
} 点击按钮变成圆圆
这样即可。改了需求只需要改displayName
计算属性可以让 某些根据其他属性计算而来的属性变成一个属性displayName是个方法,可以当作属性来用默认读取返回值
两种写法,第一种函数写法就是默认的get.
需求二 展示列表 点击男 展示男 点击女 展示女
1、不使用计算属性:需求二
注:
User不能改 删了不好弄回来,所以复制一份 到 displayUsers
filter 不会修改原数组而是得到一个新的数组
v-for 后面必须要有key
2、使用计算属性
思路: 如何计算出来呢?
result = f(user,gender) 就是一个函数传入两者得到结果
通过 uesr(列表) 和 gender(筛选的性别) 计算出来
const { users, gender } = this;
解构赋值
const users = this.users
const gender = this.gender
简化版:
computed 特性
默认有缓存:如果我依赖的属性没有变化,我的计算属性就不会再算一次
就如需求二
我进页面 计算一次
点男 计算一次 此时我再点男他就不计算了,因为没有变
Watch 监听
当数据变化时,执行一个函数
computed也是数据变了 计算出一个新的属性
所以面试常问他俩的区别
示例1 撤销
https://codesandbox.io/s/lucid-shamir-cpcw3
new Vue({
data: {
n: 0,
history: [],
inUndoMode: false //由于撤销的时候也会触发watch 所以用它来控制
},
watch: { 当n变化的时候执行这个函数,记录 n从什么变为什么
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;
console.log("ha" + this.inUndoMode);
const old = last.from;
this.n = old;
this.$nextTick(() => { 这里必须要这样写
this.inUndoMode = false;
});
}
}
}).$mount("#app");
如果这样写不行this.inUndoMode = false;
watch n 的函数会异步调用,写完之后不会立即执行上面的代码,因为watch是异步的,所有代码执行完了才会去执行,所有代码执行完了 ,它还是false还是会触发push
所以 就再异步一下 setTimeOut也行
this.nextTick也会触发
由于this.n = old在上面所以肯定时它的异步先执行
示例2 模拟computed
https://codesandbox.io/s/objective-star-vu2h3
注:
handler 就是如何处理他的变化
immediate: true就是让 第一次渲染是也触发 watch(本来watch 在进入页面第一次渲染的时候你没有变化就不会触发它 但是不触发它就显示不了我的内容)
什么叫做数据变化
对watch 来说 或者对vue的所有监听器来说 什么叫做变化
https://codesandbox.io/s/still-snowflake-m62t1?file=/src/main.js:89-540
new Vue({
data: {
n: 0,
obj: {
a: "a"
}
},
template: `
<div>
<button @click="n += 1">n+1</button>
<button @click="obj = {a:'a'}">obj = 新对象</button>//此时 obj 变了 a还是原来的值就没有变
<button @click="obj.a += 'hi'">obj.a + 'hi'</button>//注意 此时 obj没变 a变了
</div>
`,
watch: {
n() {
console.log("n 变了");
},
obj() {
console.log("obj 变了");
},
"obj.a": function() {
console.log("obj.a 变了");
}
}
}).$mount("#app");
总结 如果你把一个简单数据类型变了 那他一定变了
如果你把一个对象里面的简单类型 变了 也是变了 只做值的对比
你把一个对象地址变了 才认为你对象变了 然后依然对里面的a做值的对比
简单类型看值 复杂类型看地址
deep:true
但是 我现在有个需求 就是 只要对象中的一个属性变了 就都算obj变了 行不行 ? 行 使用 deep:true
obj:{
handler(){ console.log("obj 变了");},
deep:true
}
那就不用监听 a b啥的了 监听obj就行了
deep就是往深了看
watch的完整语法
接受一个对象[key:string]: value(string|Function|Object|Array)
function(value,oldValue){}
两个参数 vue传给你的 第一个最新的值 第二个之前的值
(){}缩写
[ f1,f2]
'methodName' 在methods中去找对应的函数
{handler:fn(触发后要执行的函数),deep:true,immediate:true}
或者在 vm(外面)/this(里面).$watch('n',function(){console.log('n变化了')},{deep:true,immediate:true})
不要使用箭头函数
箭头函数中的this是全局对象(window)
箭头函数里是没有this的,只能继承外面的this 外面没有函数
箭头函数的this是他外面函数的this
function x (){
()=>{}
}
new Vue() 只是调用 不是它外面的函数
const vm = new Vue({
watch:{
n:function(){
this === vm
}
}
})
面试题:两者的区别
1、 英译汉
computed就是计算属性的意思 watch就是监听的意思
2、各自描述 可以代码举例子
computed是用来计算出一个值的
里面的函数调用的时候不需要加()可以当属性一样用
根据依赖自动缓存 如果依赖的值不变呢 就不会重新计算
watch是用来监听的
如果某个属性变化了就会执行一个函数
有两个选项
第一个就是immediate 表示是否再第一次渲染时执行这个函数
第二个时deep 就是我们监听一个对象是否要看对象里面属性的变化