vue學習——computed&watch

這一章主要整理一下vue中computed(計算屬性)和watch(監聽屬性)的用法。

1.computed

computed主要的做的是元數據進行加工返回一個新的數據。

案例一、現在data中有firstName 和lastName兩個值,顯示全名

解決方法一:{{firstName + ' ' +  lastName}}

            這是最簡單的方法,在計算的數據量比較少的時候可以採用。

解決方法二:computed

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>name : {{name}}</p>
            </div>
            `,
        data: {
            firstName: "zhu",
            lastName: "Ming"
        },
        computed: {
            name() {
                return `${this.firstName} ${this.lastName}`;
            }
        },
    })

解決方法三:methods

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>name : {{getName()}}</p>
            </div>
            `,
        data: {
            firstName: "zhu",
            lastName: "Ming"
        },
        methods: {
            getName() {
                return `${this.firstName} ${this.lastName}`;
            }
        },
    })

可以看到其實方案二和方案三都實現的要求,但是推薦使用方案二,原因主要是:computed只有再依賴的數據發生改變的時候纔會重新計算(緩存機制),而methods在任意數據改變的時候都會重新去計算。

測試案例:

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>name1 : {{name}}</p>
                <p>name2 : {{getName()}}</p>
                <p>number: <input type="text" v-model='number' /> </p>
            </div>
            `,
        data: {
            firstName: "zhu",
            lastName: "Ming",
            number: 0
        },
        computed: {
            name() {
                console.log('recalculate computed')
                return `${this.firstName} ${this.lastName}`;
            }
        },
        methods: {
            getName() {
                console.log('recalculate methods')
                return `${this.firstName} ${this.lastName}`;
            }
        },
    })

輸出結果(當在input框中不斷改變number的值)

 

可以發現,這時候每次number的值改變都會觸發methods中的getName()方法。 

computed執行setter操作(不推薦,但是有computed有這個功能)

案例二、輸入全名,然後依據輸入的全名改變data中的firstName和lastName。

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>firstName : {{firstName}}</p>
                <p>lastName : {{lastName}}</p>
                <p>name : <input type="text" v-model='name' /> </p>
            </div>
            `,
        data: {
            firstName: "zhu",
            lastName: "Ming",
            number: 0
        },
        computed: {
            name: {
                get() {
                    console.log('recalculate computed')
                    return `${this.firstName} ${this.lastName}`;
                },
                set(name) {
                    const names = name.split(' ');
                    this.firstName = names[0];
                    this.lastName = names[1];
                }
            }
        }
    })

改變輸入框中的name,得到輸出結果:

2.watch

watch是監聽一個值的變化,然後進行一系列的操作。

案例三、還是上面的例子用watch也能實現(比較麻煩,需要監聽firstName和lastName兩個值的變化,不推薦,這裏只是作爲一個例子)。

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>firstName : <input type='text' v-model='firstName' /></p>
                <p>lastName : <input type='text' v-model='lastName' /> </p>
                <p>fullName : {{fullName}}</p>
            </div>
            `,
        data: {
            firstName: "zhu",
            lastName: "Ming",
            fullName: ''
        },
        watch: {
            firstName(newValue, oldValue) {
                this.fullName = newValue + ' ' + this.lastName;
            }
        }
    })

輸出結果:

可以看出剛開始fullName是空的,這是因爲第一次剛渲染完成的時候watch默認是不執行的,改變下firstName輸出結果:

 這樣就看到了我們想要的結果,那如果要求第一次渲染的時候就要執行watch,方法如下:

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>firstName : <input type='text' v-model='firstName' /></p>
                <p>lastName : <input type='text' v-model='lastName' /> </p>
                <p>fullName : {{fullName}}</p>
            </div>
            `,
        data: {
            firstName: "zhu",
            lastName: "Ming",
            fullName: ''
        },
        watch: {
            firstName: {
                handler(newValue, oldValue) {
                    this.fullName = newValue + ' ' + this.lastName;
                },
                immediate: true  //即時,即立刻執行的意思。
            }
        }
    })

這樣我們就可以得到第一次渲染的時候 watach方法也執行了 結果:

和上例中的immediate一樣,還有設置deep參數

deep表示監聽深度監聽

案例四、在data中有一個obj對象,需要監聽obj.a的變化

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>obj.a : <input type='text' v-model='obj.a' /></p>
                <p>obj.b : <input type='text' v-model='obj.b' /></p>
            </div>
            `,
        data: {
            obj: {
                a: 0,
                b: 'a'
            }
        },
        watch: {
            obj: {
                handler(newValue, oldValue) {
                    console.log('watch obj.a changed')
                },
                immediate: false  //即時,即立刻執行的意思。
            }
        }
    })

可以看到上例監聽了obj的變化,但是obj.a進行改變的時候,輸出結果:

說明並沒有執行watch下面監聽的函數,這時候上deep:true,再次進行測試,輸出結果:

但是,我們繼續改變obj.b的值,發現監聽又再次觸發了,其輸出結果:

這個說明,一旦加了deep:true的屬性之後,vue會遍歷監聽的obj下面說有值,但其實我們只想要監聽obj.a,而且這樣效率也低下,再次修改:只需要將監聽的obj改成'obj.a'即可

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>obj.a : <input type='text' v-model='obj.a' /></p>
                <p>obj.b : <input type='text' v-model='obj.b' /></p>
            </div>
            `,
        data: {
            obj: {
                a: 0,
                b: 'a'
            }
        },
        watch: {
            'obj.a': {
                handler(newValue, oldValue) {
                    console.log('watch obj.a changed')
                },
                immediate: false,  //即時,即立刻執行的意思。
                deep: false
            }
        }
    })

改過之後發現及時deep爲false,但是修改obj.a的時候能正常觸發監聽,改變obj.b的時候無法觸發監聽。

案例四、當在watch的中改變被監聽的值。

可以試想一下,如果監聽obj.a,你又在監聽觸發的方法中改變了obj.a的會造成什麼後果。

ok,這想必大家都知道,那就是死循環,所以千萬不要用。

    var vm = new Vue({
        el: "#app",
        template: `
            <div>
                <p>obj.a : <input type='text' v-model='obj.a' /></p>
                <p>obj.b : <input type='text' v-model='obj.b' /></p>
            </div>
            `,
        data: {
            obj: {
                a: 0,
                b: 'a'
            }
        },
        watch: {
            'obj.a': {
                handler(newValue, oldValue) {
                    this.obj.a += 1;
                    console.log('watch obj.a changed')
                },
                immediate: false,  //即時,即立刻執行的意思。
                deep: false
            }
        }
    })

稍稍改變一下a的值,可以看到結果: 

上圖結果obj.a的值還爲0是因爲,瀏覽器直接卡崩了。好了,所以千萬不要在watch監聽中去改變本身。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章