注意:vue实例中data中的属性名不能和methods、computed中的属性名重名。
computed是vue实例中的计算属性,存在缓存机制,只有它所依赖的属性值发生变化才会重新计算,否则默认走缓存。这样节省性能。
当一个属性依赖多个属性或多个属性的变化会影响另一个属性时,这个属性可以放在computed中进行处理。
当一个属性依赖多个属性时一般可以采用computed方式,当该属性依赖的其他属性发生变化时,会立即调用该属性的get方法重新计算当前的属性值并重新渲染页面。
一般放在computed中属性可以为其添加get和set方法。如果只需要对该属性设置get方法可以简写。
computed与methods的区别:computed是计算属性,默认走缓存,当依赖的属性发生变化,就会执行对应的getter方法,如果多次访问同一个属性不需要多次执行该函数,它会走缓存。但是methods中定义的函数一般是在调用时执行,不存在缓存机制。
<div id="app">
<input type="checkbox" v-model="selectAll">全选{{selectAll}}<br/>
<ul>
<li v-for="a in arr">
<input type="checkbox" v-model="a.isSelected">{{a.name}}
li>
ul>
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
let vm = new Vue({
el: "#app",//元素选择器
data: {//data中的属性不能和methods、computed中重名
arr:[{isSelected:true,name:"手机"},{isSelected:false,name:"电脑"}]
},
computed:{
selectAll:{
get(){
// 函数中this指向当前实例,当这个get函数变为箭头函数时this指向window,此时可以给这个箭头函数传递一个形参,该形参就是vue实例
return this.arr.every(item=>item.isSelected);
},
set(val){
// 会默认将最新设置的值传给第一个形参,当改变selectAll的值时就会调用set方法。此处在设置selectAll值的目的是更新所有li中的isSelected属性值
this.arr.forEach(item=>item.isSelected = val);
}
}
// 如果当前的属性只有获取数据,没有设置数据那么可以如下方式书写
// selectAll(){
// return this.arr.every(item=>item.isSelected);
// }
}
});
script>
watch只能监听data中现有的属性,只要监听的属性发生变化就会触发监听函数执行。
<div id="app">
{{a}}<button @click="fn">改变button>
div>
let vm = new Vue({
el:"#app",
data:{
a:100
},
methods:{
fn(){
this.a = 200;
}
},
watch:{
// 下面这种监听方式有一个特点第一次绑定时不执行的该监听函数的,只有监听的属性值发生变化才执行此函数
a(newVal,oldVal){//只要监听到属性a的值发生变化就会触发该监听函数执行
//newVal表示改变后的值
//oldVal表示改变前的值
console.log(newVal);//200
console.log(oldVal);//100
}
}
});
<div id="app">
姓:<input type="text" v-model="firstName"><br/>
名:<input type="text" v-model="lastName"><br/>
全名:{{fullName}}
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
let vm = new Vue({
el:"#app",
data:{
firstName:"",
lastName:""
},
computed:{
fullName(){//fullName的get方法,在它依赖的属性发生变化时才会调用该函数执行
return this.firstName + this.lastName;
}
}
});
script>
<script src="node_modules/vue/dist/vue.js">script>
<script>
let vm = new Vue({
el:"#app",
data:{
firstName:"",
lastName:"",
fullName:""
},
watch:{//watch中只能监听data中存在的属性,当属性值发生变化时调用对应的方法
firstName(newVal){
this.fullName = newVal + this.lastName;
},
lastName(newVal){
this.fullName = this.firstName + newVal;
}
}
});
script>
computed和watch的区别:
上面的举例中watch监听函数在第一次绑定时不执行,只有在监听到的属性值发生变化才会执行对应的监听函数。现在可以利用watch中的immediate属性让watch中监听函数在第一次绑定时就执行。
<div id="app">
姓:<input type="text" v-model="firstName"><br/>
名:<input type="text" v-model="lastName"><br/>
全名:{{fullName}}
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
let vm = new Vue({
el:"#app",
data:{
firstName:"",
lastName:"",
fullName:""
},
watch:{
firstName:{
handler(newVal,oldVal){
this.fullName = newVal + this.lastName;
},
immediate:true//将immediate属性设置为true后在第一次绑定firstName属性时就会触发监听函数执行
},
lastName:{
handler(newVal,oldVal){
console.log(newVal,oldVal);
this.fullName = this.firstName + newVal;
},
immediate:true
}
}
});
script>
从上面的举例中可以看出,在给 firstName 绑定了一个handler方法,之前我们写的 watch 方法其实默认写的就是这个handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler。而immediate:true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。
可以通过设置watch中的deep属性值为true,实现通过设置一个对象的监听函数,就可以监听到该对象中的属性值发生的变化。
<div id="app">
姓:<input type="text" v-model="person.firstName"><br/>
名:<input type="text" v-model="person.lastName"><br/>
全名:{{person.fullName}}
div>
<script src="node_modules/vue/dist/vue.js">script>
<script>
let vm = new Vue({
el:"#app",
data:{
person:{
firstName:"",
lastName:"",
fullName:""
}
},
watch:{
person:{
handler(newVal,oldVal){
this.person.fullName = this.person.firstName + this.person.lastName;
},
immediate:true,
deep:true//通过设置deep属性值为true可以保证在person中的属性值发生变化就会执行该监听函数
}
// 上面使用deep属性对person的监听可以写成下面的方式,针对data中的对象的单个属性进行监听
// 'person.firstName':{
// handler(newVal,oldVal){
// this.person.fullName = newVal + this.person.lastName;
// }
// },
// 'person.lastName':{
// handler(newVal,oldVal){
// this.person.fullName = this.person.firstName + newVal;
// }
// }
}
});
script>