史上最詳細 VUE2.0 全套 demo 講解 基礎3(計算屬性)

混元霹靂手發表於2017-03-28

作者 混元霹靂手-Ziksang

二天基礎1+基礎2突然突破了1000的收藏率,這使我更覺得大家認可我這種分享模式,這也看的出來vue的熱度,我在這段時間的分享中,我一直腦海裡在轉,如何用最好的demo,和更好的流程去寫文章,我相信從基礎1開始看,一定能在工作上面有很多大的收穫,接下來還是按著我們約定的來

1.本文分享 計算屬性

2.程式碼執行vue-cli 2.1版本

3.元件程式碼都在components資料夾裡

4.主程式碼邏輯都在 App.vue資料夾裡

我什麼都不要我只要

計算屬性

在計算屬性中,在我們前面基礎1和基礎2分享中有兩個地方可以計算屬性,我們認為所有屬性的計算都是變向的在過濾值,通過資料的不斷變化計算出不同的值和操作不同的方法
1.模板內的表示式
2.屬性v-bind:裡的可以進行表示式
3.指令中我們也可以進行表示式
以上三者優勢在那裡,簡潔,省程式碼量,如果只是一個小操作,比方說一些簡單的數值++,字元拼接,三元表示式,那使用相當好
以上三者的劣勢,一但要處理的邏輯複雜,如果用到if()流程控制語句,變數賦值,程式碼量大了就很難於維護,我們可能就會想到用filter,那filter的場景適用於那裡後面再說,先看一下簡單的demo

App.vue

<template>
   <div>
        <p @click="count++">{{count+'分'}}</p>
        <input v-model='message'>
        <p>{{message.split('').reverse().join('') }}</p>
   </div>
</template>
<script>
    export default {
        data () {
            return {
                count : 0,
                message : ''
            }
        }
    }
</script>複製程式碼

從上面不難看出
1.模板內使用字元拼接,ok程式碼很清楚目的的所在
2.通過指令點選,也能少一個methods方法,也很簡潔
3.通過輸入框輸入文字,在p標籤裡面進行計算轉換的時候,那我覺得語意化就不是很強烈了,那用什麼辦法呢,用filter

用filter的優勢
filter給我們用於計算和過濾一些模板表示式和v-bind:屬性表示式一些弊端的地方進行計算,他會返回當前計算的值,可以進行傳參在多地方共用這個過濾方法,
劣勢
如果我們要計算多個資料不同變化結合而成的地方那filter就能難過到了,本質上filter我認為就是1v1,對單個資料進行過濾,可以進行傳參,同方法,但不同參,非常適用

<template>
   <div>
        <input v-model='message'>
        <p>{{message | reverseString}}</p>
   </div>
</template>
<script>
    export default {
        data () {
            return {
                message : ''
            }
        },
        filters : {
            reverseString (value) {
                if(!value) return ''
                value = value.split('').reverse().join('') 
                return value
            }
        }
    }
</script>複製程式碼

我們把上個例子中第二個例子反轉字串這個方法用filter來實現,很明顯示程式碼量多了那麼一點點,但是整體的語意化相當明顯了,讓人一看這裡就要進行一些過濾計算,能過reverseString,就能知道是反轉字串

1. computed

以上說了這麼多前面的用法,因為我們模板語法和filter過濾來對computed的應用場景做一個鋪墊,劃分更加明確
computed可以做那些呢,適用於什麼場景呢?
他規避了模板語法和filter兩個所有的劣勢,他的優勢在於通過計算所有依賴的資料進行計算,然後返回一個值,記住可以依賴方法裡所有的資料,只要一個資料發生變化,則會從新計算,來更新檢視的改變,verygood,好東西看看怎麼玩

應用場景 :
這是一個簡單實用的應用場景,後面再做一個好玩的應用場景
我們填寫備註的時候我們會有一個字數的限制和字數顯示的限制,通過輸入字元,我們要提醒使用者還有輸入多少字

<template>
   <div>
        <textarea v-model="content" :maxlength="totalcount"></textarea>
        <p>你還可以輸入{{reduceCount}}字</p>
   </div>
</template>
<script>
    export default {
        data () {
            return {
                totalcount : 200 , //總共只給輸入200字
                content : ''
            }
        },
        computed : {
            reduceCount () {
                return this.totalcount - this.content.length
            }
        }
    }
</script>複製程式碼

通過一直監聽文字的字元的長度來出發compunted裡reduceCount這個方法,來再次進行計算,返回值給檢視,讓檢視進行變化。這也是一個很簡單的demo例子,那很好,前面我說了可以監聽多個資料,只要一個資料變了,整個方法就會從新計算,反饋到檢視,這個方法只是一個簡單的應用,請看下個demo例子,你們就能看懂一切的一切

這個例子是我想了一個多小時才次決定的例子,那就最就薩德事件使中韓足球最熱門的一個事件,做IT做DEMO就是要玩起來,政治我們先不討論,我們用技術來感化一下我們的愛國情
demo場景分析
1.我們要宣告那些資料
一.比賽時間 用time來維護
二.比賽雙方的進球數 用物件來維護
三.比賽的播報情況 在90分鐘內,要顯示中國領先或者韓國隊領先或者雙方僵持,如果到了90分種我們要顯示中國隊贏還是韓國隊贏,還是平局
第三個資料非常關鍵,我們用什麼來維護,可以說比賽情況是多樣化的,用一個資料去定死維護,不符合場景,那我先列出那通過改變這些變化,我們不但要檢測雙方的進球數,還要通過時間來比對,是90分鐘內,還是已經結束比賽了,來顯示不同的文案。所以我們要不斷監聽兩個維護的資料,一是比賽時間,二是比賽兩隊進球數

  <template>
   <div>
        <h1>比賽時間{{time}}s</h1>
        <h2>直播播報{{result}}</h2>
        <div>
             <p>中國隊進球數:{{team.china}}</p>
             <button @click="team.china++">點選中國隊進一球</button>
             <p>韓國隊進球數:{{team.korea}}</p>
             <button @click="team.korea++">點選韓國隊進一球</button>
        </div>
   </div>
</template>
<script>
    export default {
        created () {
            let time =  setInterval(()=>{
                this.time++
                if(this.time == 90){
                    clearInterval(time)
                }
            },1000)
        },
        data () {
            return {
                time : 0,
                team : {
                    china : 0,
                    korea : 0
                }
            }
        },
        computed : {
            result () {
               if(this.time<90){
                   if(this.team.china>this.team.korea){
                       return '中國隊領先'
                   }else if(this.team.china<this.team.korea){
                       return '韓國隊領先'
                   }else{
                       return '雙方僵持'
                   }
               }else{
                   if(this.team.china>this.team.korea){
                       return '中國隊贏'
                   }else if(this.team.china<this.team.korea){
                       return '韓國隊贏'
                   }else{
                       return '平局'
                   }
               }
            }
        }
    }
</script>複製程式碼

上面的我用點選事件來進行雙方進球數,把上面這個demo執行一下我們可以充分的理解computed的涵意,說到底是觀察一個或者多個資料,每當其中一個資料改變的時候,這個函式就會從新計算,還有就是通過觀察所有資料來維護一個狀態,就是所謂的返回一個狀態值,從上面這個demo我們就可以很容易的知道computed到底用在什麼場景,如何去維護返回一個多狀態的場景

2.methods vs computed

在methods和computed可以做同樣的事,但是,computed可以進行快取,什麼意思呢,就是在上個例子我們對比賽時間和兩個球隊的進球數進行了檢測資料,如果隨著時間的改變,但是球數沒動,對於computed來說只會從新計算這個球數會進入快取,不會再次計算,而從新計算的是這個時間,而且頁面的dom更新也會出發methods來從新計算屬性,所以如果不想讓計算屬性進入快取,請求methods,但是我推薦用computed,語議化好一點麻,什麼選項裡就應該改做什麼事,methods裡面就是應該來管事件的。個人認為,同樣的操作我就不演示demo了,看看官方的用法理解一下就可以了

3.computed vs watch

computed和watch都可以做同一件事,就像跑步運動員都可以跑步,但是分100米和1000米,術業有專功麻,兩個選項都是對資料進行時時監聽,但是兩個的適用場景就不一樣了

一.computed前面說了是適用於對多資料變動進行監聽,然後來維護一個狀態,就是返回一個狀態

二.watch是對一個資料監聽,在資料變化時,會返回兩個值 ,一個是value(當前值),二個是oldvalue是變化前的值,我們可以通過這些變化也可以去維護一個狀態,但是不符合場景,主要用於什麼地方呢?主要用於監聽一個資料來進行復雜的邏輯操作

  <template>
   <div>
        <h1>比賽時間{{time}}s</h1>
        <h2>直播播報{{result}}</h2>
        <div>
             <p>中國隊進球數:{{team.china}}</p>
             <button @click="team.china++">點選中國隊進一球</button>
             <p>韓國隊進球數:{{team.korea}}</p>
             <button @click="team.korea++">點選韓國隊進一球</button>
        </div>
   </div>
</template>
<script>
    export default {
        created () {
            let time =  setInterval(()=>{
                this.time++
                if(this.time == 90){
                    clearInterval(time)
                }
            },1000)
        },
        data () {
            return {
                time : 0,
                team : {
                    china : 0,
                    korea : 0
                },
                result : "雙方僵持"
            }
        },
        watch : {
            time (value,oldval) {
               if(value<90){
                   if(this.team.china>this.team.korea){
                       this.result =  '中國隊領先'
                   }else if(this.team.china<this.team.korea){
                       this.result =  '韓國隊領先'
                   }else{
                       this.result =  '雙方僵持'
                   }
               }else{
                   if(this.team.china>this.team.korea){
                       this.result =  '中國隊贏'
                   }else if(this.team.china<this.team.korea){
                       this.result =  '韓國隊贏'
                   }else{
                       this.result =  '平局'
                   }
               }
            },
            team (value,oldval){
                if(this.time<90){
                   if(value.china>value.korea){
                       this.result =  '中國隊領先'
                   }else if(value.china<value.korea){
                       this.result =  '韓國隊領先'
                   }else{
                       this.result =  '雙方僵持'
                   }
               }else{
                   if(value.china>value.korea){
                       this.result =  '中國隊贏'
                   }else if(value.china<value.korea){
                       this.result =  '韓國隊贏'
                   }else{
                       this.result =  '平局'
                   }
               }
            }
        }
    }
</script>複製程式碼

以上程式碼和computed的產生的效果一模一樣,但是很明顯,就像我對computedwatch闡述過了應用場景,這個場景只是維護了一個比賽的狀態,而不牽扯到邏輯操作,雖然也能完成,很明顯,無論從程式碼量的比對,還是可讀性,還是可維護性的比對都不勝於computed,但是說到底誰更強大呢,我還是老實的說watch更強大,雖然他有場景的侷限性,但是他可以做牽扯到計算屬性的一切操作,缺點watch只能一個一個監聽

watch應用場景
我想信圖片預載入大家肯定都有接觸過,當圖片量大的時候,為了保證頁面圖片都載入出來的時候,我們才把主頁面給顯示出來,再進行一些ajax請求,或者邏輯操作
那此時你用computed對這種監聽一個資料然後進行一系列邏輯操作和ajax請求,那watch再適合不過了,如果用computed的話那你連實現都實現不了,只有用watch監聽

  <template>
   <div v-show=show>
       <img src="https://img.alicdn.com/simba/img/TB14sYVQXXXXXc1XXXXSutbFXXX.jpg" alt="">
       <img src="//img.alicdn.com/tfs/TB1iZ6EQXXXXXcsXFXXXXXXXXXX-520-280.jpg_q90_.webp" alt="">
       <img src="https://img.alicdn.com/simba/img/TB1C0dOPXXXXXarapXXSutbFXXX.jpg" alt="">
       <img src="//img.alicdn.com/tfs/TB1iZ6EQXXXXXcsXFXXXXXXXXXX-520-280.jpg_q90_.webp" alt="">
   </div>
</template>
<script>
    export default {
        mounted () {
            var _this = this
            let imgs = document.querySelectorAll('img')
            console.log(imgs)
            Array.from(imgs).forEach((item)=>{
                let img = new Image()
                img.onload = ()=>{
                    this.count++
                }
                img.src=item.getAttribute('src')
            })
        },
        data () {
            return {
                count : 0,
                show : false
            }
        },
        watch : {
            count (val,oldval) {
                if(val == 4){
                    this.show = true
                    alert("載入完畢")
                    //然後可以對後臺傳送一些ajax操作
                }
            }
        }
    }
</script>複製程式碼

我們可以發現發四張圖片都載入完畢的時候頁面才顯示出來

根據完方有一句話說的很重要的一句

雖然計算屬性在大多數情況下更合適,但有時也需要一個自定義的 watcher 。這是為什麼 Vue 提供一個更通用的方法通過 watch 選項,來響應資料的變化。當你想要在資料變化響應時,執行非同步操作或開銷較大的操作,這是很有用的。

基於這個官方的理解再總結我個人的整體理解。給出computed和watch的總結,記住這幾點的總結,在做專案的時候想想這些總結,選擇你的應用方法

computed :

監聽多個資料或者一個資料來維護返回一個狀態值 ,只要其中一個或多個資料發生了變化,則會從新計算整個函式體,從新返回狀態值

watch :
只有一個一個監聽據,只要這個資料發生變化,就會在返回兩個引數,第一個是當前的值,第二個是變化前的值,每當變化的時候,則會觸發函式體的裡的邏輯行為,來進邏輯後續操作

其實我覺得計算屬性也好,computed,watch這幾個都不是有多難,如果淺層面上看很容易理解,如果從深層面上看,很多小夥伴會存在什麼問題,就是會濫用,混用,這些計算屬性,我想通過這些demo例子講解和分析,我相信你又上一層樓了,ok終於可以完結這篇了,下一篇我想看看大家想學什麼可以給我留言,如果那個多我就先講那個
1.事件處理
2.表單控制元件
3.條件渲染
4.class 和 style 繫結

渣渣前端開發工程師,喜歡鑽研,熱愛分享和講解教學, 微信 zzx1994428 QQ494755899

支援我繼續創作和感到有收穫的話,請向我打賞點吧

史上最詳細 VUE2.0 全套 demo 講解 基礎3(計算屬性)

如果轉載請標註出自@混元霹靂手ziksang

相關文章