四、Vue中的计算属性和侦听器
计算属性(computed)
举个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性与侦听器</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
姓:<input v-model="firstName" />
名:<input v-model="lastName" />
<div>{{firstName}}{{lastName}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:"",
lastName:""
}
})
</script>
</body>
</html>
这样结果就会显示两个框,一个是姓一个是名,并且在框内写什么,框的下面就会显示写的东西,效果如下:
但是还可以显示的更简洁,firstName和lastName加起来称为fullName,这样可以用一个词来表示。
利用computed属性可以达到这一点,computed表示的是一个属性可以由其他属性计算而来
显示如下:
<body>
<div id="root">
姓:<input v-model="firstName" />
名:<input v-model="lastName" />
<div>{{fullName}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:"",
lastName:""
},
computed:{
fullName:function(){
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</body>
模板中div标签显示的是fullName,fullName定义在computed里面表示其具有计算属性,是可以通过function函数计算出来的,函数中返回的是firstName和lastName,也即是fullName的计算结果。
优势:firstName和lastName不变,当再次用到fullName的时候,fullName不会计算,它会继续使用上次的缓存值;只有当fistName或者lastName其中一个值变化的时候,fullName才会重新计算。这提现的是computed属性良好的性能。
当然,也可以不用computed计算属性,只用方法methods也可以,代码如下:
<body>
<div id="root">
<div v-text="fullName()"></div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:"Li",
lastName:"Haoran"
},
methods:{
fullName:function(){
return this.firstName + " " + this.lastName
}
}
})
</script>
</body>
如上,如果v-text等号后面显示的是一个函数,那么则必须带一个小括号表示成fullName(),这样就可以显示方法了。
当然<div v-text="fullName()"></div>也可以写成<div>{{fullName()}}</div>,这样表示的是一样的。
如果用methods方法和computed计算属性实现相同的目的时,最好用computed计算属性,因为有缓存机制,只要在computed计算的内容不变的情况下,computed的内容就不需要重新计算,提高了性能;而methods方法,只要调用多少次,就会执行多少次,computed无论调用多少次,只会执行一次。
计算属性的setter和getter
<body>
<div id="app">
{{fullName}}
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Dell",
lastName:"Lee",
},
computed:{
fullName:function(){
return this.firstName +" " +this.lastName
}
}
})
</script>
</body>
上式中的computed属性的式子,函数可以写在get里面,可以写成以下的样子,即:
<body>
<div id="app">
{{fullName}}
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Dell",
lastName:"Lee",
},
computed:{
fullName:{
get:function(){
return this.firstName +" " +this.lastName
}
}
}
})
</script>
</body>
当插值表达式去读计算属性的内容的时候,就会走get的方法,这种写法和最上面的写法没有什么区别。
有读就有写,与get相对应的就是set,例子如下:
<body>
<div id="app">
{{fullName}}
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Dell",
lastName:"Lee",
},
computed:{
fullName:{
get:function(){
return this.firstName +" " +this.lastName
},
set:function(value){
var arr = value.split(" ")
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
</body>
这个set中,有一个可以写入的参数value,这个value值用split以空格来分开成数组,数组的第一个设置成firstName,第二个设置成lastName。
打开浏览器,可以看到:
点击F12,打开控制台,输入vm.fullName = "Mike Wang",回车后会发现浏览器中显示的内容也改变了:
情况是这样的:computed内的内容不变时,computed因有缓存机制导致不用重复渲染,但是输入“Mike Wang”的时候,set属性会导致firstName和lastName变化,进而导致computed中的get发生变化(fullName重新计算),结果会导致页面发生变化
侦听器(watch)
举一个需求:当姓和名中的框发生变化的时候,每发生一次变化,就计数加一,
这就用到了侦听器功能,侦听器即是定义watch属性,侦听器即是监听某一个数据的变化,可以通过设置业务逻辑,一旦数据发生变化,设置中的内容会根据数据的变化而变化。且在这个需求当中,计数变量设置为count,参数设置为0,每一次变化,count都会计数:
<body>
<div id="root">
姓:<input v-model="firstName" />
名:<input v-model="lastName" />
<div>{{fullName}}</div>
<div>{{count}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:"",
lastName:"",
count:0
},
computed:{
fullName:function(){
return this.firstName + ' ' + this.lastName
}
},
watch:{
fullName:function(){
this.count ++
}
}
})
</script>
</body>
可根据上面的式子,在框内随机写数据,得到下面的结果: