![](https://img.kancloud.cn/41/e0/41e066af9a6c25a24868d9667253ec98_1241x333.jpg)
*****
## 计算属性和监听器
一般情况下属性都是放到`data`中的,但是有些属性可能是需要经过一些逻辑计算后才能得出来,那么我们可以把这类属性变成计算属性。比如以下:
~~~
<div id="app">
<label for="length">长:</label>
<input type="number" name="length" v-model:value="length">
<label for="width">宽:</label>
<input type="number" name="width" v-model:value="width">
<label for="area">面积:</label>
<input type="number" name="area" v-bind:value="area" readonly>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
length: 0,
width: 0,
},
computed: {
area: function(){
return this.length*this.width;
}
}
});
</script>
~~~
可能有的小伙伴会觉得这个计算属性跟我们之前学过的函数好像有点重复。实际上,计算属性更加智能,他是基于它们的响应式依赖进行缓存的。也就是说只要相关依赖(比如以上例子中的`area`)没有发生改变,那么这个计算属性的函数不会重新执行,而是直接返回之前的值。这个缓存功能让计算属性访问更加高效。
## 计算属性的`set`:
计算属性默认只有`get`,不过在需要时你也可以提供一个`set`,但是提供了`set`就必须要提供`get`方法。示例代码如下:
~~~
<div id="app">
<div>
<label>省:</label>
<input type="text" name="province" v-model:value="province">
</div>
<div>
<label>市:</label>
<input type="text" name="city" v-model:value="city">
</div>
<div>
<label>区:</label>
<input type="text" name="district" v-model:value="district">
</div>
<div>
<label>详细地址:</label>
<input type="text" name="address" v-model:value="address">
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
district: "",
city: "",
province: ""
},
computed: {
address: {
get: function(){
let result = "";
if(this.province){
result = this.province + "省";
}
if(this.city){
result += this.city + "市";
}
if(this.district){
result += this.district + "区";
}
return result;
},
set: function(newValue){
let result = newValue.split(/省|市|区/)
if(result && result.length > 0){
this.province = result[0];
}
if (result && result.length > 1){
this.city = result[1];
}
if(result && result.length > 2){
this.district = result[2];
}
}
}
}
});
</script>
~~~
## 监听属性:
监听属性可以针对某个属性进行监听,只要这个属性的值发生改变了,那么就会执行相应的函数。示例代码如下:
~~~
<div id="app">
<div>
<label>搜索:</label>
<input type="text" name="keyword" v-model:value="keyword">
</div>
<div>
<p>结果:</p>
<p>{{answer}}</p>
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
keyword: "",
answer: ""
},
watch: {
keyword: function(newKeyword,oldKeyword){
this.answer = '加载中...';
let that = this;
setTimeout(function(){
that.answer = that.keyword;
},Math.random()*5*1000);
}
}
});
</script>
~~~