computed计算属性
- 被计算出来的属性就是计算属性,类似过滤器,对绑定到view的数据进行处理
- 计算属性就是当依赖的属性的值发生变化的时候,才会触发他的更改,如果依赖的值,不发生变化的时候,使用的是缓存中的属性值。
computed的getter和setter
- computed的属性可以被视为是data一样,可以读取和设值。因此,在computed中可以分为getter(读取)和setter(设值).
- 一般情况下,是没有setter的,computed只是预设了getter,也就是只能读取,不可以改变设值。所以,computed默认格式(是不表明getter函数的).
- 当赋值给计算属性的时候,将调用setter函数。多用于在模板组件中需要修改计算属性自身的值的时候。
get
<div id="example">
<p>firstName: "{{ firstName }}"</p>
<p>lastName: "{{ lastName }}"</p>
<p>fullName: "{{ fullName }}"</p>
</div>
export default {
name: "App",
data(){
return {
firstName:'张',
lastName:'小明'
}
},
computed:{
fullName: function(){
return this.firstName + ' ' + this.lastName
}
}
};
注意:fullName不可在data里面定义, 如果定义会报错,因为对应的computed作为计算属性定义fullName并返回对应的结果给这个变量,变量不可被重复定义和赋值
get+setter
正常只有getter,当给计算属性赋值的时候,就用到了setter。多用于在模板组件中需要修改计算属性自身的值的时候。
<template>
<div id="example">
<p>firstName: "{{ firstName }}"</p>
<p>lastName: "{{ lastName }}"</p>
<p>fullName: "{{ fullName }}"</p>
<p>fullName-setter: "{{ setter }}"</p>
<button @click="change">change setter</button>
</div>
</template>
<script>
export default {
name: "App",
data(){
return {
firstName:'张',
lastName:'小明',
setter:''
}
},
computed:{
fullName: {
get(){ //回调函数 当需要读取当前属性值时执行,根据相关数据计算并返回当前属性的值
return this.firstName + ' ' + this.lastName
},
set(val){//监视当前属性值的变化,当属性值发生变化时执行,更新相关的属性数据
console.log(val)//val就是fullName的最新属性值
this.firstName = '使用了setter'
}
}
},
methods:{
change(){
this.fullName = '使用了setter' //触发了fullName的set
}
}
};
</script>
只有当计算属性中的属性被直接赋值的时候,才会走setter函数,而且,setter函数和getter函数是相互独立的,不是说,走setter函数,就必须走getter函数。
computed注意事项
- 缓存:
- 如果依赖的属性没有发生变化,就不会重新计算,而是立即返回之前的计算结果。
- 当模板中不使用fullName,即使firstName发生改变之后,也不会走computed。不是说我们更改了getter中使用的变量(即依赖的属性),就会触发computed的更新,他有一个前提是computed里的值必须要在模板中使用才可以。、
watch 监听/侦听
watch监听一个值的变化。 当firstName发生变化时,监听并且执行。
<div>
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
new Vue({
el: '#root',
data: {
firstName: 'Dawei',
lastName: 'Lou',
fullName: ''
},
watch: {
firstName(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
}
}
})
immediate
上面的例子是值变化时候,watch才执行,我们想让值最初时候watch就执行就用到了handler和immediate属性
watch: {
firstName: {
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法,如果设置了false,那么效果和上边例子一样
immediate: true
}
}
deep
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
new Vue({
el: '#root',
data: {
cityName: {id: 1, name: 'shanghai'}
},
watch: {
cityName: {
handler(newName, oldName) {
// ...
},
deep: true, //设置deep: true 则可以监听到cityName.name的变化
immediate: true
}
}
})
此时会给cityName的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。
如果只需要监听对象中的一个属性值,则可以做以下优化:使用字符串的形式监听对象属性:
watch: {
'cityName.name': {
handler(newName, oldName) {
// ...
},
deep: true,
immediate: true
}
}
watch总结
- 不支持缓存,数据变,直接会触发相应的操作;
- watch支持异步;
- 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
- 当一个属性发生变化时,需要执行对应的操作;一对多;
- 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数, * immediate:组件加载立即触发回调函数执行, * deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
watch和computed
- 从属性名上,computed是计算属性,也就是依赖其它的属性计算所得出最后的值
- watch是去监听一个值的变化,然后执行相对应的函数。
- 从实现上,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算。
- watch在每次监听的值变化时,都会执行回调。其实从这一点来看,都是在依赖的值变化之后,去执行回调。
- 很多功能本来就很多属性都可以用,只不过有更适合的。如果一个值依赖多个属性(多对一),用computed肯定是更加方便的。如果一个值变化后会引起一系列操作,或者一个值变化会引起一系列值的变化(一对多),用watch更加方便一些。
- watch的回调里面会传入监听属性的新旧值,通过这两个值可以做一些特定的操作。immediate表示是否第一次渲染就执行这个函数。deep:是否坚挺这个对象里面的属性的变化。computed通常就是简单的计算。
- atch和computed并没有哪个更底层,watch内部调用的是vm.$watch,它们的共同之处就是每个定义的属性都单独建立了一个Watcher对象。