vuejs计算属性computed & 监听属性watch
vuejs计算属性computed & 监听属性watch
一、计算属性computed
1.1 什么是计算属性
computed是vue的计算属性,是根据依赖关系进行缓存的计算,只有在它的相关依赖发生改变时才会进行更新。
<template>
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
</template>
<script>
export default {
name: "CT",
data() {
return {
message: "Hello",
};
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split("").reverse().join("");
},
},
};
</script>
可以像绑定普通 property 一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。
1.2 computed默认使用的是getter属性
在vue组件中使用reversedMessage属性,vue会自动调用computed下的reversedMessage方法。
1.3 computed的响应式依赖(缓存)
computed的每一个计算属性都会被缓存起来,只要计算属性所依赖的属性发生变化,计算属性就会重新执行,视图也会更新。下面代码中,计算属性total,它依赖了a和b这两个属性,只要它们其中一个属性变化,total就会重新执行。computed计算属性会被缓存,在下面代码中使用了两次total,但在控制台只输出了一次compouted total。
<template>
<div>
<p>BT</p>
<a @click="addA()">addA</a> | <a @click="addB()">addB</a>
<p>total: {{ total }}</p>
<p>total: {{ total }}</p>
</div>
</template>
<script>
export default {
name: "BT",
data() {
return {
a: 1,
b: 2,
};
},
computed: {
total() {
console.log("compouted total ");
return this.a + this.b;
},
},
mounted() {},
methods: {
addA() {
this.a++;
},
addB() {
this.b++;
},
},
};
</script>
1.4 计算属性的 getter 与 setter
在 Vue 中,computed 的属性可以被视为是data 一样,可以读取和设值,因此在 computed 中可以分成 getter(读取) 和 setter(设值),一般情况下是没有 setter 的,computed 预设只有 getter ,也就是只能读取,不能改变设值。
vue.js计算属性默认只有 getter,因为是默认值所以我们也常常省略不写,如下代码:
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
其实computed里的代码完整的写法应该是:
computed: {
fullName: {
get(){
return this.firstName + ' ' + this.lastName
}
}
}
计算属性settter
computed: {
fullName: {
get(){
return this.firstName + ' ' + this.lastName
},
set(newVal){
console.log(newVal)
}
}
}
1.5 计算属性小结
- 计算属性在
computed写的属性不要在data重复写,跟data中的数据一样可以通过vm.获取或者修改 - 只要获取某个计算属性就会触发对应的
get函数 - 只要是依赖的值(必须有
setter和getter响应的数据)发生改变了就会重新计算自己的值 computed的每一个计算属性都会被缓存起来,只要计算属性所依赖的属性发生变化,计算属性就会重新执行,视图也会更新。- 计算属性必须要有
get可以没有set - 在
set中不要给计算属性重新赋值,否则会产生死循环 第一次获取的时候依赖值没有发生改变但是也会默认执行一次
二、watch
2.1 watch用来处理什么场景
在vue中watch用来监听数据的变化,一旦发生变化可以执行一些其他操作。
<template>
<div>
<p>BT</p>
<a @click="addA()">addA</a> | <a @click="addB()">addB</a>
<p>a: {{ a }}</p>
<p>b: {{ b }}</p>
</div>
</template>
<script>
export default {
name: "BT",
data() {
return {
a: 1,
b: 2,
};
},
computed: {},
watch: {
a() {
console.log('a watch');
}
},
mounted() {},
methods: {
addA() {
this.a++;
},
addB() {
this.b++;
},
},
};
</script>
2.2 watch参数
watch就是当值第一次绑定的时候,是不会执行监听函数的,只有值发生改变才会执行。如果需要在第一次绑定的时候也执行函数,则需要用到immediate属性,比如当父组件向子组件动态传值时,子组件props首次获取到父组件传来的No认知时,也需要执行函数handler方法:immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化时才执行deep,当需要监听一个对象的变化时,普通的watch方法无法监听对象内部属性的变化,只有data中的数据才能够坚挺到变化,此时需要deep属性进行深度监听,设置deep: true,当对象的属性较多时,每个属性的变化都会执行handler
<template>
<div>
<p @click="click()">AT</p>
<BT :age="age"></BT>
</div>
</template>
<script>
import BT from "./BT.vue";
export default {
name: "AT",
components: { BT },
data() {
return {
age: 10,
};
},
methods: {
click() {
this.age = Math.floor(Math.random() * 20 + 18);
},
},
};
</script>
<template>
<div>
<p>BT</p>
<a @click="nameChange()">nameChange</a> |
<a @click="ageChange()">ageChange</a>
<p>name: {{ person.name }}</p>
<p>age: {{ person.age }}</p>
</div>
</template>
<script>
export default {
name: "BT",
props: {
age: {
type: Number,
},
},
data() {
return {
person: {
name: "BT",
age: 20,
},
};
},
computed: {},
watch: {
person: {
handler(newVal, oldVal) {
console.log("newVal: ", newVal, "oldVal: ", oldVal);
},
deep: true,
immediate: true
},
age: {
handler(newVal, oldVal) {
console.log("newVal: ", newVal, "oldVal: ", oldVal);
},
immediate: true
},
},
mounted() {},
methods: {
nameChange() {
this.person.name = "BT" + new Date();
},
ageChange() {
this.person.age = Math.floor(Math.random() * 20 + 18);
},
},
};
</script>
2.3 监听对象
watch可以监听对象,也可以监听对象中的某个属性。注意在监听对象时,可以通过配置deep参数来决定是否要深度监听。
<template>
<div>
<p>BT</p>
<a @click="nameChange()">nameChange</a> |
<a @click="ageChange()">ageChange</a>
<p>name: {{ person.name }}</p>
<p>age: {{ person.age }}</p>
</div>
</template>
<script>
export default {
name: "BT",
data() {
return {
person: {
name: "BT",
age: 20,
},
};
},
computed: {},
watch: {
person: {
handler(newVal, oldVal) {
console.log("newVal: ", newVal, "oldVal: ", oldVal);
},
deep: true
},
"person.age": {
handler(newVal, oldVal) {
console.log("newVal: ", newVal, "oldVal: ", oldVal);
},
},
},
mounted() {},
methods: {
nameChange() {
this.person.name = "BT" + new Date();
},
ageChange() {
this.person.age = Math.floor(Math.random() * 20 + 18);
},
},
};
</script>
2.4 不要使用箭头函数
watch中不要使用箭头函数,即不要用箭头函数来定义watcher函数。因为箭头函数中的this是指向当前作用域,对于箭头函数来说,箭头函数中的this指向的是定义时的对象而不是函数运行时所在的对象,即全局定义时的window对象。
三、watch 和 computed 的区别
computed的get必须有返回值(return),而watchreturn可有可无computed支持缓存,只有依赖的数据发生改变,才会重新进行计算,而watch不支持缓存,数据发生改变,会直接触发相应的操作computed可以自定义名称,而watch只能监听props和data里面名称相同的属性computed适用于复杂的运算,而watch适合一些消耗性功能,比如Ajaxcomputed不支持异步,当computed内有异步操作是无效,无法监听数据的变化,而watch支持异步computed属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值,而watch监听的函数接受两个参数,第一个是最新的值,第二个是输入之前的值- 如果一个属性是由其他属性计算而来的,这个属性
依赖其他属性,多对一或者一对一,一般用computed;当一个属性发生变化时,需要执行对应的操作,一对多,一般用watch
参考
更多推荐



所有评论(0)