5.Vue 计算属性和侦听器
Hello,我是 Alex 007,一個熱愛計算機編程和硬件設計的小白,為啥是007呢?因為叫 Alex 的人太多了,再加上每天007的生活,Alex 007就誕生了。
5.Vue 計算屬性和偵聽器
這篇文章我們來看一下Vue的計算屬性和偵聽屬性。計算屬性是自動監聽依賴值的變化,從而動態返回內容,監聽是一個過程,在監聽的值變化時,可以觸發一個回調,并做一些事情。偵聽屬性watch中可以執行代碼邏輯,如函數節流,Ajax異步獲取數據,甚至操作 DOM。
計算屬性
模板內的表達式非常便利,但是設計它們的初衷是用于簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如:
<div id="example">{{ message.split('').reverse().join('') }} </div>在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這里是想要顯示變量 message 的翻轉字符串。當你想要在模板中多處使用翻轉字符串,就會更加難以處理。
所以,對于這種復雜邏輯,Vue給我們提供了更好的解決方案,計算屬性。
基礎例子
<!DOCTYPE html> <html><head><meta charset="utf-8"><title></title><script src="vue.js"></script></head><body><div id="app"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{{ reversedMessage }}"</p></div><script type="text/javascript">var app = new Vue({el: '#app',data: {message: 'Hello'},computed: {reversedMessage: function () {return this.message.split('').reverse().join('')}}})</script></body> </html>插值表達式{{ reversedMessage }}首先會去data中找 reversedMessage 這個屬性,如果找不到就再去計算屬性中去找,找到之后再將它顯示在頁面上。
這里我們聲明了一個計算屬性 reversedMessage。我們提供的函數將用作 property app.reversedMessage 的 getter 函數:
console.log(app.reversedMessage) // => 'olleH' app.message = 'Goodbye' console.log(app.reversedMessage) // => 'eybdooG'你可以打開瀏覽器的控制臺,自行修改例子中的 app。app.reversedMessage 的值始終取決于 app.message 的值。
你可以像綁定普通 property 一樣在模板中綁定計算屬性。Vue 知道 app.reversedMessage 依賴于 app.message,因此當 app.message 發生改變時,所有依賴 app.reversedMessage 的綁定也會更新。而且最妙的是我們已經以聲明的方式創建了這種依賴關系:計算屬性的 getter 函數是沒有副作用 (side effect) 的,這使它更易于測試和理解。
計算屬性緩存 vs 方法
你可能已經注意到計算屬性和我們之前講過的method有些類似,可以通過在表達式中調用方法來達到同樣的效果:
<p>Reversed message: "{{ reversedMessage() }}"</p> // 在組件中 methods: {reversedMessage: function () {return this.message.split('').reverse().join('')} }我們可以將同一函數定義為一個方法而不是一個計算屬性。兩種方式的最終結果確實是完全相同的。然而,不同的是計算屬性是基于它們的響應式依賴進行緩存的。只在相關響應式依賴發生改變時它們才會重新求值。這就意味著只要 message 還沒有發生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函數。
這也同樣意味著下面的計算屬性將不再更新,因為 Date.now() 不是響應式依賴:
computed: {now: function () {return Date.now()} }相比之下,每當觸發重新渲染時,調用方法將總會再次執行函數。
我們為什么需要緩存?假設我們有一個性能開銷比較大的計算屬性 A,它需要遍歷一個巨大的數組并做大量的計算。然后我們可能有其他的計算屬性依賴于 A。如果沒有緩存,我們將不可避免的多次執行 A 的 getter!如果你不希望有緩存,請用方法來替代。
計算屬性的 setter
在 Vue 中,computed 的屬性可以被視為跟 data 一樣,可以讀取和設值,因此在 computed 中可以分成 getter(讀取) 和 setter(設值),一般情況下是沒有 setter 的,computed 預設只有 getter ,也就是只能讀取,不能改變設值。
計算屬性默認只有 getter,不過在需要時你也可以提供一個 setter:
<!DOCTYPE html> <html><head><meta charset="utf-8"><title></title><script src="vue.js"></script></head><body><div id="app"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{{ reversedMessage }}"</p></div><script type="text/javascript">var app = new Vue({el: '#app',data: {message: 'Hello'},computed: {reversedMessage: {get() {return this.message.split('').reverse().join('')},set(value) {this.message = value}}}})</script></body> </html>現在再運行 app.reversedMessage = "Alex" 時,setter 會被調用,app.reversedMessage 會相應地被更新。
偵聽屬性
雖然計算屬性在大多數情況下更合適,但有時也需要一個自定義的偵聽屬性。這就是為什么 Vue 通過 watch 選項提供了一個更通用的方法,來響應數據的變化。當需要在數據變化時執行異步或開銷較大的操作時,watch方式是最有用的。
例如,我們可以寫一個類似于《答案之書》的小東西。
答案之書,是一本重新定義了讀者-作者關系的書。 它的每一頁都寫有一句有關選擇或行動的答案,當你為生活中紛擾繁雜的小事猶豫不決的時候,隨意翻開其中一頁,讓這本書幫你做決定。
<!DOCTYPE html> <html><head><meta charset="utf-8"><title></title><script src="vue.js"></script></head><body><div id="app"><p>Ask a yes/no question:<input v-model="question"></p><p>{{ answer }}</p></div><script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script><script>var app = new Vue({el: '#app',data: {question: '',answer: 'I cannot give you an answer until you ask a question!'},watch: {question(newQuestion, oldQuestion) {this.answer = 'Waiting for you to stop typing...'this.getAnswer()}},methods: {getAnswer() {if (this.question.indexOf('?') === -1) {this.answer = 'Questions usually contain a question mark.'return}this.answer = 'Thinking...'var self = thisaxios.get('https://yesno.wtf/api').then(response => {self.answer = response.data.answer}).catch(function(error) {self.answer = 'Error! Could not reach the API. ' + error})}}})</script></body> </html>3在這個示例中,使用 watch 選項允許我們執行異步操作 (訪問一個 API),并在我們得到最終結果前,設置中間狀態。這些都是計算屬性無法做到的。
計算屬性 vs 偵聽屬性
偵聽屬性是Vue 提供的一種更通用的方式去觀察和響應 Vue 實例上的數據變動。當你有一些數據需要隨著其它數據變動而變動時,你很容易濫用 watch——特別是如果你之前使用過 AngularJS。然而,通常更好的做法是使用計算屬性而不是命令式的 watch 回調。
我們來看一個很簡單的例子,快手前端實習生的面試題:兩個輸入框和一個顯示框,計算兩個輸入框的和。
<!DOCTYPE html> <html><head><meta charset="utf-8"><title></title><script src="vue.js"></script></head><body><div id="app"><input type="number" v-model="a"><span>+</span><input type="number" v-model="b"><span>=</span><span>{{ sum }}</span></div><script type="text/javascript">const app = new Vue({el:'#app',data:{a: 0,b: 0,sum: 0,},watch:{a(value) {this.sum = parseInt(value) + parseInt(this.b)},b(value) {this.sum = parseInt(this.a) + parseInt(value)}}})</script></body> </html>上面代碼是命令式且重復的。我們用計算屬性的版本進行比較:
const app = new Vue({el:'#app',data:{a: 0,b: 0,},computed:{sum(){return parseInt(this.a) + parseInt(this.b)}} })好得多了,不是嗎?
最后我們再回顧一下這節課的內容:計算屬性是自動監聽依賴值的變化,從而動態返回內容,監聽是一個過程,在監聽的值變化時,可以觸發一個回調,并做一些事情。偵聽屬性watch中可以執行代碼邏輯,如函數節流,Ajax異步獲取數據,甚至操作 DOM。
總結
以上是生活随笔為你收集整理的5.Vue 计算属性和侦听器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 96. Unique Binary Se
- 下一篇: 785. Is Graph Bipart