[Vue 牛刀小試]:第五章 - 計算屬性與監聽器

 1、前言

  在 Vue 中,咱們能夠很方便的將數據使用插值表達式( Mustache 語法)的方式渲染到頁面元素中,可是插值表達式的設計初衷是用於簡單運算,即咱們不該該對差值作過多的操做。當咱們須要對差值作進一步的處理時,這時,咱們就應該使用到 Vue 中的計算屬性來完成這一操做。同時,當差值數據變化時執行異步或開銷較大的操做時,咱們能夠經過採用監聽器的方式來達到咱們的目的。html

  學習系列目錄地址:http://www.javashuo.com/article/p-bzzucmub-ba.htmlvue

  倉儲地址:https://github.com/Lanesra712/VueTrial/blob/master/Chapter01-Rookie/watcher.htmlgit

 2、乾貨合集

  一、計算屬性

  計算屬性,通常是用來描述一個屬性值依賴於另外一個的屬性值,當咱們使用插值表達式將計算屬性綁定到頁面元素上時,計算屬性會在依賴的屬性值的變化時自動的更新 DOM 元素。例如在下面的代碼中,咱們在 computed 中,定義了一個 reversedMessage 屬性,它能夠根據咱們的 data 中的 message 屬性的變化自動的獲取到反轉後的 message 的屬性值。github

<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 中定義一個方法來實現這個需求。原來,計算屬性的本質就是一個方法,只不過,咱們在使用計算屬性的時候,是把計算屬性的名稱直接當作屬性來使用,而並不會把計算屬性當作一個方法去調用。segmentfault

  那麼,爲何咱們還要去使用計算屬性而不是去定義一個方法呢?原來,計算屬性是基於它們的依賴進行緩存的。即只有在相關依賴發生改變時它們纔會從新求值。例如在上面的例子中,只要 message 的屬性值沒有發生改變,不管任何使用咱們使用到 reversedMessage 屬性,都會當即返回以前的計算結果,而沒必要再次執行函數。數組

  反之,若是你使用方法的形式實現,當你使用到 reversedMessage 方法時,不管 message 屬性是否發生了改變,方法都會從新執行一次,這無形中增長了系統的開銷。固然,你也能夠本身在方法中實現根據依賴進行緩存,嗯,若是你不嫌煩的話。。。緩存

  在上面的案例中,對於 reversedMessage 這個計算屬性來講,咱們主要的目的是爲了獲取屬性的值,即便用的是計算屬性的 getter 方法。不過,若是你須要使用到計算屬性的 setter 方法時,咱們也是能夠爲計算屬性提供一個 setter 方法的。app

<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。異步

  二、監聽屬性

  在 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>

 3、總結

  一、計算屬性的結果會被緩存起來,只有依賴的屬性發生變化時纔會從新計算,必須返回一個數據,主要用來進行純數據的操做。

  二、監聽器主要用來監聽某個數據的變化,從而去執行某些具體的回調業務邏輯,不只僅侷限於返回數據。

 4、參考

  一、深刻理解 Vue Computed 計算屬性

  二、Vue 2.0學習筆記: Vue中的computed屬性

  三、Vue系列之computed使用詳解

相關文章
相關標籤/搜索