1.computed
1.1 定义
computed是计算属性,依赖于其他属性值进行计算,具有缓存性,当computed依赖的值发生改变时,computed才会再次进行计算。
1.2 使用
<template>
<div>
{{ fullName }}
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
firstName: 'Dell',
lastName: 'Lee'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
}
</script>
这里不可在data中重复声明fullName,否则会报如下图错误,因为在计算属性会定义并返回结果给变量fullName,变量不可重复定义和赋值。
1.3 get & set
get是根据计算属性获取当前computed返回的数据
set是监听computed返回的计算属性的变化
下面用一个实例来分析一下 get和 set的具体使用
<template>
<div>
姓:<input v-model="firstName"><br>
名:<input v-model="lastName"><br>
姓名一:<input v-model="fullName1"><br>
姓名二:<input v-model="fullName2"><br>
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
firstName: 'Dell',
lastName: 'Lee'
}
},
computed: {
fullName1() { // 返回当前computed计算属性的值
return this.firstName + ' ' + this.lastName
},
fullName2: {
get() { // get返回当前computed计算属性的值
return this.firstName + ' ' + this.lastName
},
set(val) { // 监听当前computed计算属性值的变化,当属性值变化后,更新相关的源计算属性数据
console.log(val) // fullName的值
const names = val.split(' ') // 将字符串分隔成字符串数组
console.log(names)
this.firstName = names[0] // 当fullName变化时,将这个变化同步给firstName和lastName
this.lastName = names[1]
}
}
}
}
</script>
根据 姓 和 名 计算出姓名值 其中,姓名一的绑定是单向的, 姓名二的绑定是双向的。
1.当 姓 、名 改变时,姓名一、姓名二根据依赖的属性值进行计算 得到最终的姓名
2.当姓名一改变时, 姓、名 、姓名二都不会发生变化
3.当姓名二改变时,姓、名、姓名一 随着发生变化
改变fullName2, set()中获取到当前的值为 Dell2 Lee3 ,通过set中的操作,更改了依赖的源属性数据,当源属性数据改变时,fullName1也发生改变。
结合上边的代码进行分析,
1.computed 是计算属性,依赖firstName和lastName计算出姓名,当依赖的属性改变时,计算属性的返回值跟着变化。
2.姓名一 fullName1 的绑定是单向的,即 姓、名 改变,姓名一改变, 姓名一改变,姓、名 不改变。因为fullName1只设置了get
3.姓名二 fullName2 的绑定是双向的,即姓、名 改变,姓名二改变, 姓名二改变,姓、名 改变。因为fullName2设置了get和set
get获取当前computed所计算的属性值,set监听当前computed计算的属性值发生变化,变化后,将这种变化同步到依赖的属性值。
2.watch
2.1定义
watch为监听器,来响应数据的变化,当数据发生改变时,触发watch中的函数。
2.2使用
2.2.1简单数据类型
简单数据类型可直接监听
<template>
<div>
<input v-model="inputVal">
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
inputVal: ''
}
},
watch: {
inputVal() {
console.log(this.inputVal)
}
}
}
</script>
2.2.2 复杂数据类型
当监听对象等复杂数据类型时,直接监听,不能起作用
<template>
<div>
<input v-model="listQuery.inputVal">
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
listQuery: { inputVal: '' }
}
},
watch: {
listQuery() {
console.log(this.listQuery)
}
}
}
</script>
当输入框输入值的时候,并没有监听到相应的值的变化
启用深度监听
<template>
<div>
<input v-model="listQuery.inputVal">
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
listQuery: { inputVal: '' }
}
},
watch: {
listQuery: {
handler(oldVal, newVal) {
console.log(oldVal)
console.log(newVal)
},
immediate:true,
deep: true // 深度监听
}
}
}
</script>
可以发现,当启用深度监听后,可以监听到复杂数据类型的变化,但得到的值是一样的。之所以oldVal和newVal的值是一样的,原因在于它们的引用是同一个对象,watch不会保留数据的变化。
immediate属性
最初绑定的时候是不会执行的,要等到监听的值改变时才执行监听计算。那我们想要一开始就让他最初绑定的时候就执行需要设置immediate。
immediate:true
设置了immediate之后,刷新页面的时候控制台就输出了最初绑定的值。
deep属性
deep启用深度监听,不设置deep,无法监听到复杂数据类型的属性值变化。
简单数据监听和复杂数据监听
注意二者之间的写法是不同的
watch: {
inputVal(oldVal, newVal) {
console.log(oldVal, newVal)
}
}
watch: {
listQuery: {
handler(oldVal, newVal) {
console.log(oldVal, newVal)
},
immediate: true,
deep: true
}
}
handler 表示对象中属性变化的处理函数,这个函数只能叫这个名字,唯一不可变
解决方法一、 监听对象的某一属性
<template>
<div>
<input v-model="listQuery.inputVal">
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
listQuery: { inputVal: '' }
}
},
watch: {
'listQuery.inputVal': {
handler(oldVal, newVal) {
console.log(oldVal,newVal)
}
}
}
}
</script>
解决方法二、 结合computed计算属性实现对象的监听
<template>
<div>
<input v-model="listQuery.inputVal">
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
listQuery: { inputVal: '' }
}
},
computed: {
input() {
return this.listQuery.inputVal
}
},
watch: {
input(oldVal, newVal) {
console.log(oldVal, newVal)
}
}
}
</script>
以上结合computed完成了对象的监听。
综上所述,简单总结一下:
computed 会依赖缓存中的计算属性值,当所依赖的属性值计算结果发生改变时才会再次触发而watch只要监听的数据重新渲染,不管值是否发生 发生变化都会触发,这样会导致性能上的降低。
二者都是用于监听数据,具体用法结合实际应用。