iT邦幫忙

6

[筆記][Vue.js]打開Vue.js世界的大門(5)-太複雜的事情就交給computed吧!

嗨啊!大家好!經過昨天耍了一天廢後,今天繼續闖蕩Vue世界吧!

孔子說「溫故而知新」所以在進入正文之前我們先簡單複習一下資料綁定,看能不能因此獲得新的知識XD
HTML

<div id="baseVue">
    {{text}}
</div>

JavaScript

let textData = {
    text:'Hello!World!'
}

let showText = new Vue({
    el:'#baseVue',
    data:textData
})

OK!不管有看前幾篇,或是沒看過的大大們,應該都知道textData.text的資料會綁定到HTML{{text}}上面,這叫做單向綁定,雙向綁定小弟在此就不說了,其實包著text的兩個括號內,是可以寫下JavaScript的表達式的,什麼是表達式呢?讓我們在不動到JavaScript的狀態下看一下HTML的改變:

<div id="baseVue">{{ '這是加在前面的文字' + text}}</div>

https://ithelp.ithome.com.tw/upload/images/20180822/20106935ewu1WCyU5G.jpg
看(我不是在罵髒話XD)!畫面上除了原本繫結的Hello!World!外又多了前面加上去的字串,這時候你可能會想說,我是在裝笑維嗎?要這樣寫不如直接寫成這是加在前面的文字{{text}},還可以不用單引號和加號!沒錯!如果你心中有閃過一絲這樣子的想法就對了,不過這只是個小例子嘛!再給我一次機會吧!一樣在修改一下HTML

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

貼心PS時間:

  1. str.split(s):把字串str用s分隔成一個陣列,空字串就是每個字元都放一個位置。
  2. arr.reverse():把陣列中的內容反轉,[1,2,3]變[3,2,1]。
  3. arr.join(s):把陣列內的所有內容串成字串,每個索引間都穿插字元s,空字串就是不穿插。

好的,結束PS時間,結果如下:
https://ithelp.ithome.com.tw/upload/images/20180822/20106935zDP93UO44i.jpg
沒看錯!在Vue.js的{{}}中可以使用任何函式,就算我把他切割成陣列,再反轉,再組合成字串,只要確定該行是一個表達式,那我保證Vue.js不會讓你失望。

好的,那就繼續...什麼?你說表達式到底是什麼?簡單來說,就是可以產生出一個值的句子,就叫做表達式,但是別想在{{}}中宣告變數哦!那個就做敘述句而不是表達式。

那接下來我們就會想,可是如果把處理資料的邏輯寫在前面的繫結,這邊一塊那邊一塊,也太不方便了吧!而且如果以後要改一個地方,又要去找哪邊有這些表達式去一個一個改...所以!我們就有了一個救星!

computed!

這個計算屬性是繼eldatamethods之後出現的第四個團員,官方直接翻譯他叫計算屬性,如果有需要像上面那樣把data的資料放在畫面上的許多地方,又必須做一些處理後再綁定,那就可以直接把處理資料的邏輯寫在計算屬性中,例如我將上一個例子修改一下:
HTML

<div id="baseVue">
    <!--這裡改成繫結computed內的屬性名稱-->
    {{reText}}
</div>

JavaScript

let textData = {
    text:'Hello!World!'
}

let showText = new Vue({
    el:'#baseVue',
    data:textData,
    computed:{
        //在computed中創建一個reText屬性來放剛剛的表達式
        reText:function(){
            /*這裡的this指向showText這個實體
            可以從實體物件去取我們放在data中的資料
            也可以直接透過textData去取值*/
            return this.text.split('').reverse().join('')
        }
    }
})

https://ithelp.ithome.com.tw/upload/images/20180822/201069355mUdy1MPlt.jpg
我可沒有用同一張圖,是得出來的結果真的和上方一模一樣,所以把邏輯整理在computedHTML就輕鬆的綁定資料,如果以後要改直接從computed中去修改,而且上述例子的reText因為有使用到textDatatext的資料,所以當textData.text的資料發生改變了,computed就會重新計算新值並綁定到畫面上:
https://ithelp.ithome.com.tw/upload/images/20180823/20106935vUxp1RksWJ.jpg
但是相反的,如果值沒有發生改變computed是不會重新計算值綁定到畫面上的,他會把第一次的值存在緩存中,一直到資料改變了,才會重新計算並寫入新值到緩存裡,所以官方舉了下面的例子:
HTML

<div id="timeVue">
    {{now}}
</div>

JavaScript

let timeVue = new Vue({
    el:'#timeVue',
    computed:{
        now:() => Date()
    }
})

https://ithelp.ithome.com.tw/upload/images/20180823/20106935ARuAHxvSI1.jpg
他會讓剎那變永恆,因為沒有他並沒有使用到data中的任何資料(當然上面的例子也沒有data),所以沒有使用的data發生改變,那computed就不會重新計算新值!

這樣看起來computed不只會讓HTML更乾淨,還可以把整理好的邏輯整理在物件中,但是更想不到的是我們剛剛做的只是一半而已,上半段使用的名字是耳熟能詳的getter;既然有getter那絕對也少不了setter

等等,雖然功能是一樣的,但為什麼剛剛都沒去指定getter屬性?好的,這個問題非常容易,因為gettercomputed的屬性中是預設的!如果需要用到setter的話就必須像下方的例子一樣,好好寫清楚才行!
HTML

<div id="nameVue">
    {{name}}
</div>

JavaScript

let nameData = {
    //這邊如果有打反了還請留言告訴我XD,我再修正
    firstName : 'Tom',
    lastName : 'Cruise',
}

//把計算屬性拆出來
let nameComputed = {
    name:{
        //取值,把姓氏和名字加起來回傳
        get:() => nameData.firstName + ' ' + nameData.lastName,
        
        //設值,這裡的val是指定給name的值
        set:(val) => {
            //把val用一個空格分割成陣列,因為姓和名中間通常有空白
            let name = val.split(' ')
            //給值,姓給firstName,名字給lastName
            nameData.firstName = name[0]
            nameData.lastName = name[1]
        }
    }
}

let nameVue = new Vue({
    el:'#nameVue',
    data:nameData,
    computed:nameComputed,
})

getter的結果:
https://ithelp.ithome.com.tw/upload/images/20180823/20106935nW0x35lcE0.jpg
setter的結果:
https://ithelp.ithome.com.tw/upload/images/20180823/20106935CFSbnOONR3.jpg
上面例子的nameComputed是我把資料邏輯的物件拆出來,之後再指定給nameVuecomputed屬性,可以看到和之前不一樣的是,我在name裡面又放了兩個屬性「getset」,分別區分取值的時候執行什麼,設值的時候又執行什麼,而setfunction有一個參數,那裡是我們賦予他的新值,所以可以直接拿來處理寫入的部分!

小小題外話,不知道有沒有人注意到在最後一個例子的computed中,我是直接對nameData做操作和取值,並沒有使用this,因為在JavaScriptES6語法,箭頭函式是依照定義函式時的物件去指定this,而不是使用時的物件,這點是我剛剛不小心踩到的雷點,想說怎麼值都跑不出來XD,和大家分享一下!


連存取器都可以用上,是不是覺得computed是個好東西XD,就算我現在還沒在實務中使用到他,光想著就對他愛不釋手了!文章的最後還是感謝各位大大的觀看!如果內容有任何觀念錯誤或解釋不清楚的地方,再麻煩留言告訴我,我會盡快修正的!謝謝大家/images/emoticon/emoticon41.gif


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
小碼農米爾
iT邦高手 1 級 ‧ 2018-08-23 01:39:40

挖!! computed 真不錯,像可快取的 method,在 ng1 通常會用函數處理,
感覺 Vue 很多特性都解決了 ng1 會碰到的問題,難怪大家會喜歡。
還以為 ES6 的 lambda 和一般函數一樣,原來有差異。 /images/emoticon/emoticon37.gif

Homura iT邦高手 1 級 ‧ 2018-08-23 11:39:16 檢舉

GitHub上Vue的星數也比NG2高
NG2上手難度有點高,變成只適合大型專案
還有那叫箭頭函式不叫lambda啊/images/emoticon/emoticon16.gif

NG2 會花很多時間在架構上,開發小專案不太適合。

哈哈哈,原來是這樣,C# 習慣看到箭頭函式就等於 Lambda,而 JS 一般的匿名函數就是 Lambda。

0
jack1234552000
iT邦新手 5 級 ‧ 2019-08-30 22:55:34

這章 講到了
分開資料跟處理過的資料
讓其更好管理

在computed裏頭
有預設的存取器
預設是get 只要取用就可以顯示
也就是不需要另外再寫get

接著講到set的概念
關於這個set 跟中間有張圖 也看了好久一直搞不懂
一直以為要name.set('Vim Diesel') 這樣設定
後來才理解
nameVue.name = 'Vim Diesel'
這個其實就是set的概念

把'Vim Diesel' 帶進val這個參數
去函數處理這個字串
藉由set修改nameData的資料
進而改變畫面的繪製

謝謝超人你第五天的教學

神Q超人 iT邦研究生 5 級 ‧ 2019-09-02 08:39:24 檢舉

哈哈,謝謝你一直發漏我的學習歷程,也感受到你認真的態度!
雖然我已經不在 Vue 世界了,但還是很開心之前留下來的東西可以在陪著同時期的人一起成長:)

我要留言

立即登入留言