一、前言 在 Vue 中,我們可以很方便的將數據使用插值表達式( Mustache 語法)的方式渲染到頁面元素中,但是插值表達式的設計初衷是用於簡單運算,即我們不應該對差值做過多的操作。當我們需要對差值做進一步的處理時,這時,我們就應該使用到 Vue 中的計算屬性來完成這一操作。同時,當差值數據變化 ...
一、前言
在 Vue 中,我們可以很方便的將數據使用插值表達式( Mustache 語法)的方式渲染到頁面元素中,但是插值表達式的設計初衷是用於簡單運算,即我們不應該對差值做過多的操作。當我們需要對差值做進一步的處理時,這時,我們就應該使用到 Vue 中的計算屬性來完成這一操作。同時,當差值數據變化時執行非同步或開銷較大的操作時,我們可以通過採用監聽器的方式來達到我們的目的。
學習系列目錄地址:https://www.cnblogs.com/danvic712/p/9549100.html
倉儲地址:https://github.com/Lanesra712/VueTrial/blob/master/Chapter01-Rookie/watcher.html
二、乾貨合集
1、計算屬性
計算屬性,一般是用來描述一個屬性值依賴於另一個的屬性值,當我們使用插值表達式將計算屬性綁定到頁面元素上時,計算屬性會在依賴的屬性值的變化時自動的更新 DOM 元素。例如在下麵的代碼中,我們在 computed 中,定義了一個 reversedMessage 屬性,它可以根據我們的 data 中的 message 屬性的變化自動的獲取到反轉後的 message 的屬性值。
<div id="app"> 輸入的值:<input type="text" v-model="message"><br /> 反轉的值:{{reversedMessage}} </div> <script> var vm = new Vue({ el: '#app', data: { message: '' }, computed: { reversedMessage: function () { //這裡的 this 指向 當前的 vm 實例 return this.message.split('').reverse().join('') } }, methods: {} }) </script>
可能你會發覺,這裡的寫法和我們定義方法時很相似,我們完全也可以在 methods 中定義一個方法來實現這個需求。原來,計算屬性的本質就是一個方法,只不過,我們在使用計算屬性的時候,是把計算屬性的名稱直接當做屬性來使用,而並不會把計算屬性當做一個方法去調用。
那麼,為什麼我們還要去使用計算屬性而不是去定義一個方法呢?原來,計算屬性是基於它們的依賴進行緩存的。即只有在相關依賴發生改變時它們才會重新求值。例如在上面的例子中,只要 message 的屬性值沒有發生改變,無論任何使用我們使用到 reversedMessage 屬性,都會立即返回之前的計算結果,而不必再次執行函數。
反之,如果你使用方法的形式實現,當你使用到 reversedMessage 方法時,無論 message 屬性是否發生了改變,方法都會重新執行一次,這無形中增加了系統的開銷。當然,你也可以自己在方法中實現根據依賴進行緩存,嗯,如果你不嫌煩的話。。。
在上面的案例中,對於 reversedMessage 這個計算屬性來說,我們主要的目的是為了獲取屬性的值,即使用的是計算屬性的 getter 方法。不過,如果你需要使用到計算屬性的 setter 方法時,我們也是可以為計算屬性提供一個 setter 方法的。
<div id="app"> 輸入的值:<input type="text" v-model="message"><br /> 反轉的值:{{reversedMessage}} </div> <script> var vm = new Vue({ el: '#app', data: { message: '' }, computed: { reversedMessage: { get: function () { return this.message.split('').reverse().join('') }, set: function (value) { this.message = value.split('').reverse().join('') } } }, methods: {} }) </script>
在上面的代碼中,我們為計算屬性 reversedMessage 增加了一個 setter 方法:通過設置 reversedMessage 的值,同樣進行反轉操作,並最終將結果賦值給屬性 message。
2、監聽屬性
在 vue 中,我們不光可以使用計算屬性的方式來監聽數據的變化,還可以使用 watch 監聽器的方法來監測某個數據發生的變化。不同的是,計算屬性僅僅是對於依賴數據的變化後進行的數據操作,而 watch 更加側重於對於監測中的某個數據發生變化後所執行的一系列的業務邏輯操作。
監聽器以 key-value 的形式定義,key 是一個字元串,它是需要被監測的對象,而 value 則可以是字元串(方法的名稱)、函數(可以獲取到監聽對象改變前的值以及更新後的值)或是一個對象(對象內可以包含回調函數的其它選項,例如是否初始化時執行監聽 immediate,或是是否執行深度遍歷 deep,即是否對對象內部的屬性進行監聽)。
1)回調值為函數方法
在下麵的例子中,我們監聽了 message 屬性的變化,根據屬性的變化後執行了回調方法,列印出了屬性變化前後的值。
<div id="app"> 輸入的值:<input type="text" v-model="message"> </div> <script> var vm = new Vue({ el: '#app', data: { message: '' }, computed: {}, watch: { //回調為未創建的方法 'message': function (newValue, oldValue) { console.log(`新值:${newValue} --------- 舊值:${oldValue}`) } }, methods: {} }) </script>
同樣的,我們可以通過方法名稱指明回調為已經定義好的方法。
<div id="app"> 輸入的值:<input type="text" v-model="message"> </div> <script> var vm = new Vue({ el: '#app', data: { message: '' }, computed: {}, watch: { //回調為已創建好的方法 'message': 'recording' }, methods: { recording: function (newValue, oldValue) { console.log(`method記錄:新值:${newValue} --------- 舊值:${oldValue}`) } } }) </script>
2)回調值為對象
當我們監聽的回調值為一個對象時,我們不僅可以設置回調函數,還可以設置一些回調的屬性。例如,在下麵的例子中,我們監聽了 User 這個對象,同時執行了執行深度遍歷,這時,當我們監聽到 User.name 這個屬性發生改變的時候,我們就可以執行我們的回調函數。註意,深度遍歷預設為 false,當不啟用深度遍歷時,我們是無法監聽到對象的內部屬性的變化的。
<div id="app"> 用戶姓名:<input type="text" v-model="User.name"> </div> <script> var vm = new Vue({ el: '#app', data: { message: '', User: { name: 'zhangsan', gender: 'male' } }, computed: {}, watch: { //回調為對象 'User': { handler: function (newValue, oldValue) { console.log(`對象記錄:新值:${newValue.name} --------- 舊值:${oldValue.name}`) }, deep: true } }, methods: {} }) </script>
可能你發現了,為什麼 newValue 與 oldValue 都是一樣的啊?原來,當我們監聽的數據為對象或數組時,newValue 和 oldValue 是相等的,因為對象和數組都為引用類型,這兩個的形參指向的也是同一個數據對象。同時,如果我們不啟用深度遍歷,我們將無法監聽到對於 User 對象中 name 屬性的變化。
<div id="app"> 用戶姓名:<input type="text" v-model="User.name"> </div> <script> var vm = new Vue({ el: '#app', data: { message: '', User: { name: 'zhangsan', gender: 'male' } }, computed: {}, watch: { //回調為對象 'User': { handler: function (newValue, oldValue) { console.log(`對象記錄:新值:${newValue.name} --------- 舊值:${oldValue.name}`) }, deep: false } }, methods: {} }) </script>
三、總結
1、計算屬性的結果會被緩存起來,只有依賴的屬性發生變化時才會重新計算,必須返回一個數據,主要用來進行純數據的操作。
2、監聽器主要用來監聽某個數據的變化,從而去執行某些具體的回調業務邏輯,不僅僅局限於返回數據。
四、參考
2、Vue 2.0學習筆記: Vue中的computed屬性