Vue Computed Properties、Methods、Watch Properties

Vue:2.5

如果我們有一個需求是要反轉字串,直接針對特定字串做的話,會長這樣:

<div id="app">
    {{ message.split('').reverse().join('') }}
</div>

假設這個功能是需要大量使用的話,勢必得封裝成一個 Mehtod 以供使用。
而在 Vue 中就有許多不同的做法可以解決相同的問題。

Computed Properties

Computed 是 Vue 提供的 計算屬性,可以將一些邏輯運算的程式定義在此,變成一個動態的屬性。因此,在Computed 第一次計算過後,會將結果 cache 起來,再根據相依的 data 是否有改變而決定要不要重新計算。

Notice: Computed 是屬性不是 method,因此使用時並不需要在句尾加 ()

範例

<div id="app">
    {{ reversedMessage }}
</div>
const vm = new Vue({
    el: '#app',
    data: {
        message: 'Hello Johnson'
    },
    computed: {
        reversedMessage: function () {
            console.log('run');
            return this.message.split('').reverse().join('');
        }
    }
});

// 根據上面範例,呼叫多次 reversedMessage ,只會執行到一次 console.log(run),剩的都是直接輸出 Computed cahce 的資料。
vm.reversedMessage;
vm.reversedMessage;
vm.reversedMessage;

Computed 也可以自行定義 gettersetter method,讓使用上更彈性。

範例

const vm = new Vue({
    el: '#app',
    data: {
        lastName: 'Lu',
        firstName:  'Johnson'
    },
    computed: {
        fullName: {
            get: function () {
                return this.firstName + ' ' + this.lastName;
            },
            set: function (value) {
                let names = value.split(' ');

                this.firstName = names[0];
                this.lastName = names[names.length - 1];
            }
        }
    }
});

// 如果沒有特別設定,預設就只會有 getter
console.log(vm.fullName);

// 當值改變時,會呼叫 setter method
vm.fullName = 'Jacky Wu';
console.log(vm.firstName);

Notice: Computed 的使用情境就是用來實現 SSOT(Single Source of Truth) 原則的。

最簡單的例子就是 單位換算,以幣值來說,你的來源只要有 新台幣,接著就可以透過 Computed 動態使用多種幣值。

Methods

Methods 就是封裝一般 method 的地方,跟 Computed 唯一的差別,就是每次執行不管相依的 data 有沒有改變,都是重新做計算。

範例

const vm = new Vue({
    el: '#app',
    data: {
        message: 'Today is '
    },
    methods: {
        methodGetTime: function () {
            return this.message + ' ' + Date.now();
        },
    },
    computed: {
        computedGetTime: function () {
            return this.message + ' ' +  Date.now();
        }
    }
});

// Computed 因為 vm.message 未改變,因此值都會相同
// Methods 會每次改變
console.log('Computed: ' + vm.computedGetTime);
console.log('Methods: ' + vm.methodGetTime());

console.log('Computed: ' + vm.computedGetTime);
console.log('Methods: ' + vm.methodGetTime());

vm.message = 'Tomorrow is ';

// vm.message 改變後,Computed 跟著重新計算
console.log('Computed: ' + vm.computedGetTime);
console.log('Methods: ' + vm.methodGetTime());

Watch Property

Watch 是用來監測你的 data 改變後,需要做些什麼事。有些情境使用 WatchComputed 都可以達到效果,端看自己對於需求的定義是什麼。

範例

const vm = new Vue({
    el: '#app',
    data: {
        lastName: 'Lu',
        firstName:  'Johnson',
        fullName: 'Johnson Lu'
    },
    watch: {
        // Key 的名稱需要與 data 名稱相同
        // 只要設定的值有改變,就會執行
        firstName: function (value) {
            this.fullName =  value + ' ' + this.lastName;
        },
        lastName: function (value) {
            this.fullName = this.firstName + ' ' + value;
        }
    }
});

也可以透過 callback handler 搭配 immediatedeep 等屬性做更彈性的使用。

範例

const vm = new Vue({
    el: '#app',
    data: {
        lastName: 'Lu',
        firstName:  'Johnson',
        fullName: 'Johnson Lu',
        people: [
            {id: 1, name: 'Johnson Lu'},
            {id: 2, name: 'Joyce Lu'}
        ]
    },
    watch: {
        firstName: {
            handler: function (value, oldValue) {
                this.fullName =  value + ' ' + this.lastName;
            },
            // immediate 為 true 時,在綁定後會先觸發一次 handler
            immediate: true
        },
        people: {
            handler: function (value, oldValue) {
                console.log(value[0].name);
            },
            // Watch 預設只會監測最上面一層,如果需要多層就必須設定 deep 屬性
            deep: true
        }
    }
});
Categories: Vue