# 第三章 計算屬性
>[success] 可在此處查看運行文檔中的代碼示例結果:[https://github.com/jianyaoo/Vue](https://github.com/jianyaoo/Vue)
[toc]
## 基礎
**<span style="padding-top:15px;display:inline-block">背景</span >**
插值語法可以在模板中使用表達式進行計算,目的是用于簡單計算。但是當邏輯比較復雜且比較多時,會使模板太過繁重而難以維護。
**<span style="padding-top:15px;display:inline-block;">用處</span>**
計算屬性用于處理復雜邏輯的表達式。
**<span style="padding-top:15px;display:inline-block;">如何使用</span>**
計算屬性在模板中與普通屬性用法一致。但是寫在實例的computed屬性內,一般是一個函數,執行結果返回一個確切的值。
**<span style="padding-top:15px;display:inline-block;">基礎示例</span>**
```JavaScript
<body>
<div id="app">
<p>{{getNewData}}</p>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"hello,vue",
},
computed:{
getNewData:function () {
return this.msg.split(",").reverse().join("&");
},
},
})
</script>
</body>
```
## 計算屬性的setter方法
計算屬性默認只有getter函數,所以一般來說:計算屬性是一個可以返回確切值得函數(即默認的getter函數)。但是也可以手動設置setter函數觸發一些事件。
**<span style="padding-top:15px;display:inline-block;">觸發方法</span>**
手動修改計算屬性的值得時候就會觸發計算屬性的setter方式。**修改計算屬性的值得方法和修改普通屬性的值的方法一致,例如上例中修改計算屬性的值則為:vm.getNewData = "hello,world"**
**<span style="padding-top:15px;display:inline-block;">代碼實例</span>**
```
<body>
<div id="app">
<p>{{updataNewData}}</p>
<button @click="handleClick">設置msg值</button>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"hello,vue",
},
computed:{
updataNewData:{
get:function () {
console.log("計算屬性");
return this.msg.split(",").reverse().join("!!!");
},
set:function (value) {
this.msg = value;
},
}
},
methods:{
handleClick:function () {
this.updataNewData = "seen,flag";
}
}
})
</script>
</body>
```
**<span style="padding-top:15px;display:inline-block;">執行說明</span>**
* 在模板中首先渲染的為msg的vue!!!hello
* 點擊按鈕,修改計算屬性的值,觸發計算屬性的setter函數
* setter函數修改了計算屬性的依賴屬性值
* 計算屬性重新計算,重新渲染最后模板渲染為flag!!!seen
## 計算屬性的緩存
>[info] 計算屬性的本質是一個可以返回確切值的函數,所以能夠通過計算屬性實現的代碼使用methods屬性定義的函數能夠達到相同的目的。
**<span style="padding-top:15px;display:inline-block;">計算屬性的緩存機制</span>**
計算屬性時基于依賴值進行緩存的。當依賴值不發生變化的時候,計算屬性就不會重新請求,可以直接獲取到計算屬性的值。只有依賴值發生改變的時候,計算屬性才會重新執行計算。
**<span style="padding-top:15px;display:inline-block;">計算屬性 vs 函數</span>**
什么時候使用計算屬性,性能開銷比較大。比如大量數組且要做大量計算時,又有其他計算屬性依賴該屬性時。
什么時候時候函數,需要傳參且不需要緩存
**<span style="padding-top:15px;display:inline-block;">計算屬性與函數的代碼實例</span>**
```
<body>
<div id="app">
<p>{{updataNewData}}</p>
<p>{{getMessage()}}</p>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"hello,vue",
},
computed:{
updataNewData:function(){
return this.msg.split(",").reverse().join("!!!");
},
},
methods:{
getMessage:function () {
return this.msg.split(",").reverse().join("!!!")
}
}
})
</script>
</body>
```
## 計算屬性與偵聽屬性
**<span style="padding-top:15px;display:inline-block;">什么是偵聽屬性</span>**
偵聽屬性是寫在實例的watch屬性中的函數,偵聽某個值,當該值發生變化時觸發監聽函數
**<span style="padding-top:15px;display:inline-block;">代碼實例</span>**
```
<body>
<div id="app">
<p>{{getMessage()}}</p>
<p>{{watchMsg}}</p>
<button @click="handleClick">設置msg值</button>
</div>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"hello,vue",
watchMsg:""
},
computed:{
getNewData:function () {
return this.msg.split(",").reverse().join("!!!");
},
},
watch:{
msg:function (val) {
this.watchMsg = this.msg.split(",").reverse().join("!");
}
},
methods:{
handleClick:function () {
this.msg= "seen,flag";
}
}
})
</script>
</body>
```
**<span style="padding-top:15px;display:inline-block;">監聽和計算屬性的區別</span>**
* 監聽屬性有一個對應的監聽字段,用來記錄值變化后產生的影響。即案例中的watchMsg
* 計算屬性是當依賴值發生變化時,修改函數的返回值。
* 偵聽屬性是偵聽值發生變化時觸發偵聽事件,直接修改偵聽屬性的值
## 偵聽器
> 當數據變化時需要異步或者開銷比較大時,可以使用自定義的偵聽器。