溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue.js 計算屬性computed

發(fā)布時間:2020-07-08 19:19:07 來源:網(wǎng)絡(luò) 閱讀:3566 作者:frwupeng517 欄目:開發(fā)技術(shù)

計算屬性


通常我們會在模板中綁定表達(dá)式,模板是用來描述視圖結(jié)構(gòu)的。如果模板中的表達(dá)式存在過多的邏輯,模板會變得臃腫不堪,維護(hù)變得非常困難。因此,為了簡化邏輯,當(dāng)某個屬性的值依賴于其他屬性的值時,我們可以使用計算屬性。


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


在這種情況下,模板不再簡單和清晰。在實現(xiàn)反向顯示 message 之前,你應(yīng)該確認(rèn)它。這個問題在你不止一次反向顯示 message 的時候變得更加糟糕。


1、什么是計算屬性

計算屬性就是當(dāng)其依賴屬性的值發(fā)生變化時,這個屬性的值會自動更新,與之相關(guān)的DOM部分也會同步自動更新。


<div id="example">
    <input type="text" v-model="didi">
    <input type="text" v-model="family">
    <br>
    didi=`didi`, family=`family`, didiFamily=`didiFamily`
</div>
<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el:'#example',
        data:{
            didi:'didi',
            family:'family'
        },
        computed:{
            //一個計算屬性的getter
            didiFamily:function(){
                //this指向vm實例
                return this.didi + this.family
            }
        }
    })
</script>

當(dāng)vm.didi和vm.family的值發(fā)生了變化時,vm.didiFamily的值會自動更新,并且會自動同步更新DOM部分

Vue.js  計算屬性computed

前面實例只提供了getter,實際上除了getter,我們還可以設(shè)置計算屬性的setter。

<div id="example">
    <input type="text" v-model="didi">
    <input type="text" v-model="family">
    <input type="text" v-model="didiFamily">
    <br>
    didi=`didi`, family=`family`, didiFamily=`didiFamily`
</div>
<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el:'#example',
        data:{
            didi:'didi',
            family:'family'
        },
        computed:{
            didiFamily:{
                //一個計算屬性的getter
                get:function(){
                    return this.didi + ''+this.family
                },
                //一個計算屬性的setter
                set:function(newVal){
                    var names = newVal.split('');
                    this.didi = names[0];
                    this.family = names[1];
                }
            }
        }
    })
</script>


當(dāng)設(shè)置vm.didiFamily的值時,vm.didi和vm.family的值也會自動更新

Vue.js  計算屬性computed

如果還不是很理解上面這段內(nèi)容的意思,那我們可以看一個簡單一點的例子:

<div id="app">
    a=>`a`
    <br>
    b=>`b`
</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm= new Vue({
        el:'#app',
        data:{
            a:1
        },
        //computed里面可以放置一些業(yè)務(wù)邏輯代碼,一定要記得return
        computed:{ //computed里面的a 是屬性,不是函數(shù)
            b:function(){ //默認(rèn)調(diào)用 getter
                return 2
            }
        }
    })
</script>


盡管data 里面沒有聲明屬性 b,但是我們通過computed 返回了一個屬性b,并返回了一個b的屬性值2,查看頁面效果截圖:

Vue.js  計算屬性computed

此時,我們可以在控制臺通過給 屬性a 重新賦值,并將新的賦值渲染到HTML頁面上

Vue.js  計算屬性computed


a的值變成了30,但是b 的值還是2,沒有發(fā)生任何變化,我們也可以把屬性a 和 屬性b 關(guān)聯(lián)起來:

<div id="app">
    a => `a`
    <br>
    b => `b`
</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            a:1
        },
        computed:{
            b:function(){
                return this.a + 1
            }
        }
    });
    document.onclick = function(){
        vm.a = 100;
    }
</script>


點擊頁面以后,屬性a 重新賦值為100,屬性b 變成了101

Vue.js  計算屬性computed

如果反過來,我們想通過b 來改變a,可以嗎?不妨在原代碼的基礎(chǔ)上試一試:

Vue.js  計算屬性computed

當(dāng)重新給b 賦值時,頁面中的a 和 b 都沒有發(fā)生任何變化。我們剛剛說到,computed里面的 b默認(rèn)調(diào)用的是 getter,其實,還有一個setter。

示例代碼:

<div id="app">
    a => `a`
    <br>
    b => `b`
</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            a:1
        },
        computed:{
            b:{
                get:function(){
                    return this.a +1
                },
                set:function(value){
                    this.a = value
                }
            }
        }
    });
    document.onclick = function(){
        vm.a = 100;
    }
</script>


從代碼中可以看到,屬性b 接受的值是在 a 的基礎(chǔ)上加1,屬性b 設(shè)置的值是直接賦給a 的。所以重新給b賦值為300時,是把a 變成了300,b在a的基礎(chǔ)上加1

Vue.js  計算屬性computed




再來看一個官方提供的例子:

<div id="example">
    <p>Original message: "`message`"</p>
    <p>Computed reversed message: "`reversedMessage`"</p>
</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el:'#example',
        data:{
            message:'Hello'
        },
        computed:{
            //a computed getter
            reversedMessage: function(){
                return this.message.split('').reverse().join('')
            }
        }
    })
</script>

Vue.js  計算屬性computed

這里我們聲明了一個計算屬性 reversedMessage 。我們提供的函數(shù)將用作屬性 vm.reversedMessage 的 getter 。

console.log(vm.reversedMessage) // -> 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // -> 'eybdooG'


你可以打開瀏覽器的控制臺,修改 vm 。 vm.reversedMessage 的值始終取決于 vm.message 的值。


你可以像綁定普通屬性一樣在模板中綁定計算屬性。 Vue 知道 vm.reversedMessage 依賴于 vm.message ,因此當(dāng) vm.message 發(fā)生改變時,依賴于 vm.reversedMessage 的綁定也會更新。而且最妙的是我們是聲明式地創(chuàng)建這種依賴關(guān)系:計算屬性的 getter 是干凈無副作用的,因此也是易于測試和理解的。

Vue.js  計算屬性computed


2、計算緩存 vs Methods

上例的效果我們也可以通過調(diào)用表達(dá)式中的method來實現(xiàn):

<p>Reversed message: "{{ reverseMessage() }}"</p>
// in component
methods: {
    reverseMessage: function () {
        return this.message.split('').reverse().join('')
    }
}


不經(jīng)過計算屬性,我們可以在 method 中定義一個相同的函數(shù)來替代它。對于最終的結(jié)果,兩種方式確實是相同的。然而,不同的是計算屬性是基于它的依賴緩存。計算屬性只有在它的相關(guān)依賴發(fā)生改變時才會重新取值。這就意味著只要 message 沒有發(fā)生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結(jié)果,而不必再次執(zhí)行函數(shù)。


這也同樣意味著如下計算屬性將不會更新,因為 Date.now() 不是響應(yīng)式依賴:

computed: {
    now: function () {
        return Date.now()
    }
}


相比而言,每當(dāng)重新渲染的時候,method 調(diào)用總會執(zhí)行函數(shù)。


我們?yōu)槭裁葱枰彺??假設(shè)我們有一個重要的計算屬性 A ,這個計算屬性需要一個巨大的數(shù)組遍歷和做大量的計算。然后我們可能有其他的計算屬性依賴于 A 。如果沒有緩存,我們將不可避免的多次執(zhí)行 A 的 getter !如果你不希望有緩存,請用 method 替代。



3、計算屬性 vs Watched Propety

Vue.js 提供了一個方法 $watch ,它用于觀察 Vue 實例上的數(shù)據(jù)變動。當(dāng)一些數(shù)據(jù)需要根據(jù)其它數(shù)據(jù)變化時, $watch 很誘人 —— 特別是如果你來自 AngularJS 。不過,通常更好的辦法是使用計算屬性而不是一個命令式的 $watch 回調(diào)。思考下面例子:

<div id="demo">{{ fullName }}</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#demo',
        data: {
            firstName: 'Foo',
            lastName: 'Bar',
            fullName: 'Foo Bar'
        },
        watch: {
            firstName: function (val) {
                this.fullName = val + ' ' + this.lastName
            },
            lastName: function (val) {
                this.fullName = this.firstName + ' ' + val
            }
        }
    })
</script>


上面代碼是命令式的和重復(fù)的。跟計算屬性對比:

var vm = new Vue({
    el: '#demo',
    data: {
        firstName: 'Foo',
        lastName: 'Bar'
    },
    computed: {
        fullName: function () {
            return this.firstName + ' ' + this.lastName
        }
    }
})



4、計算setter

計算屬性默認(rèn)只有 getter ,不過在需要時你也可以提供一個 setter :

<div id="demo">{{ fullName }}</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#demo',
        data: {
            firstName: 'Foo',
            lastName: 'Bar',
            fullName: 'Foo Bar'
        },
        computed: {
            fullName: {
                // getter
                get: function () {
                    return this.firstName + ' ' + this.lastName
                },
                // setter
                set: function (newValue) {
                    var names = newValue.split(' ')
                    this.firstName = names[0]
                    this.lastName = names[names.length - 1]
                }
            }
        }
    })
</script>


現(xiàn)在在運行 vm.fullName = 'Steven Cury' 時, setter 會被調(diào)用, vm.firstName 和 vm.lastName 也會被對應(yīng)更新。

Vue.js  計算屬性computed



5、常見問題

(1)、計算屬性getter不執(zhí)行的場景

當(dāng)計算屬性依賴的數(shù)據(jù)屬性發(fā)生改變時,計算屬性的getter方法會執(zhí)行。但是在有些情況下,雖然依賴數(shù)據(jù)屬性發(fā)生了改變,但計算屬性的getter方法并不會執(zhí)行。


當(dāng)包含計算屬性的節(jié)點被移除并且模板中其他地方?jīng)]有再引用該屬性時,那么對應(yīng)的計算屬性的getter方法不會執(zhí)行

<div id="example">
    <button @click="toggleShow">Toggle Show Total Price</button>
    <p>`totalPrice`</p>
    <p v-if="showTotal">Total Price = `totalPrice`</p>
</div>

<script src="http://cdn.bootcss.com/vue/1.0.26/vue.js"></script>
<script>
    new Vue({
        el:'#example',
        data:{
            showTotal:true,
            basePrice:100
        },
        computed:{
            totalPrice:function(){
                return this.basePrice+1;
            }
        },
        methods:{
            toggleShow:function(){
                this.showTotal = !this.showTotal
            }
        }
    })
</script>


當(dāng)點擊按鈕是showTotal為false時,此時P元素會被移除,在P元素內(nèi)部的計算屬性totalPrice的getter方法不會執(zhí)行。但是當(dāng)計算屬性一直出現(xiàn)在模板中時,getter方法還是會被執(zhí)行

Vue.js  計算屬性computed Vue.js  計算屬性computed


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI