在vue中處理復雜的邏輯的時候,我們經常使用計算屬性computer,但是很多時候,我們會把計算屬性、方法和偵聽器搞混淆,在 w3cplus.com的一篇文章中是這樣總結這三者的。
methods
:正如他的名字一樣,它們是掛載在對象上的函數,通常是Vue實例本身或Vue組件。computed
:屬性最初看起來像一個方法,但事實卻又不是方法。在Vue中,我們使用data
來跟蹤對特定屬性的更改,得到一定的反應。計算屬性允許我們定義一個與數據使用相同方式的屬性,但也可以有一些基於其依賴關系的自定義邏輯。你可以考慮計算屬性的另一個視圖到你的數據。watchers
:這些可以讓你了解反應系統(Reactivity System)。我們提供了一些鈎子來觀察Vue存儲的任何屬性。如果我們想在每次發生變化時添加一些功能,或者響應某個特定的變化,我們可以觀察一個屬性並應用一些邏輯。這意味着觀察者的名字必須與我們所觀察到的相符。
如果僅僅只是看這段話,可能還是不能很清除的明白三者的區別,我們可以通過相關的實例來對三者進行區分。
computed
計算屬性是根據依賴關系進行緩存的計算,並且只在需要的時候進行更新。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="./vue.js"></script> </head> <body> <div id="demo"> <p>原數據{{message}}</p> <p>反轉后的數據{{reversedMessage}}</p> <button @click="add()">補充貨物1</button> <div>總價為:{{price}}</div> </div> <script> var demo = new Vue({ el: '#demo', data: { message :'abcdefg', package: { count: 5, price: 5 }, }, computed:{ reversedMessage:function(){ return this.message.split('').reverse().join('') }, price: function(){ return this.package.count*this.package.price } }, methods: { add: function(){ this.package.count++ } } }) </script> </body> </html>
上面的例子中展示了計算屬性的兩種用法:一個計算屬性里面可以完成各種復雜的邏輯,最終返回一個結果;計算屬性可以依賴多個vue實例的數據,只要其中一個任何一個數據發生變化,計算屬性就會重新執行,視圖也會更新。除此之外,計算屬性還可以依賴其他計算屬性和其他實例的數據。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="./vue.js"></script> </head> <body> <div id="app1">{{text}}</div> <div id="app2">{{ reverseText}}</div> <script> var app1 = new Vue({ el: '#app1', data: { text: 'computed' } }); var app2 = new Vue({ el: '#app2', computed: { reverseText: function(){ return app1.text.split('').reverse().join(''); } } }); </script> </body> </html>
methods
在使用vue的時候,可能會用到很多的方法,它們可以將功能連接到事件的指令,甚至只是創建一個小的邏輯就像其他函數一樣被重用。接下來我們用方法實現上面的字符串反轉。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="./vue.js"></script> </head> <body> <div id="demo"> <p>原數據{{message}}</p> <p>反轉后的數據{{ reversedMessage() }}</p> </div> <script> var demo = new Vue({ el: '#demo', data: { message :'abcdefg', num:5 }, methods:{ reversedMessage(){ return this.message.split('').reverse().join('') }, } }) </script> </body> </html>
雖然使用計算屬性和methods方法來實現反轉,兩種方法得到的結果是相同的,但本質是不一樣的,計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變的時候才會重新求值,這就意味着只要message還沒有發生改變,多次訪問reversedMessage計算屬性立即返回的是之前計算的結果,而不會再次執行計算函數,而對於methods方法,只要發生重新渲染,methods調用總會執行該函數。
如果某個計算屬性a需要的遍歷一個極大的數組和做大量的計算,可以減小性能開銷,如果不希望有緩存,則用methods。
watch
watch屬性是一個對象,鍵是需要觀察的表達式,值是對應回調函數,回調函數得到的參數為新值和舊值。值也可以是方法名,或者包含選項的對象。偵察器對於任何更新的東西都有用——無論是表單輸入、異步更新還是動畫。vue實例在實例化時調用$watch(),遍歷watch對象的每一個屬性。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="./vue.js"></script> </head> <body> <div id="demo"> <button @click='a++'>a加1</button> <p>{{message}}</p> </div> <script> var demo = new Vue({ el: '#demo', data: { message :'', a:1 }, watch:{ a:function(val,oldval){ this.message = 'a的舊值為' + oldval + ',新值為' + val; } } }) </script> </body> </html>
深度監聽
在上面的例子中,監聽的簡單的數據類型,數據改變很容易觀察,但是當需要監聽的數據變為對象類型的時候,上面的監聽方法就失效了,因為上面的簡單數據類型屬於淺度監聽,對應的對象類型就需要用到深度監聽,只需要在上面的基礎上加上deep: true就可以了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="vue.js"></script> </head> <body> <div id="app"> <div v-for="item in list"> <input type="text" v-model="item.val" /> </div> </div> <script src="vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { list:[ {val: ''}, {val:''} ] }, watch: { list:{ handler: function (val, oldVal) { alert('數據改變了'); }, deep: true } }, }) </script> </body> </html>