iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
Modern Web

菜鳥學前端,一起vue起來 !系列 第 18

Day 18. 計算屬性(Computed) VS 偵聽屬性(Watched Property)

  • 分享至 

  • xImage
  •  

昨天拿computed跟methods做比較,今天換來跟watch比比看過五關斬六將ヾ(´︶`*)ノ♬

Watchers 偵聽器

大部分情況可以用computed,但如果是非同步、消耗較大較複雜的操作比較適合用watch。

Watch沒有cache的機制,但有連動的概念,資料產生行為,資料觸發行為(資料變了會去呼叫function),比較不適合單純處理普通資料(資料馬上產出資料比較適合用computed),算是萬用型但容易被濫用。

來一個Watch的小範例 σ`∀´)σ

下面的範例我們用 v-model 綁定 input 的值為 question,當我們在輸入問題的時候,watch 裡面的 question function會執行,methods裡的getAnswer也會執行,再送出 AJAX 去取得答案傳回來。

this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
這裡使用了 lodash.js 的 debounce 函式,設定在使用者輸入停止 500 毫秒的時候,會先確認有沒有問號,接著才發送 AJAX 去取得問題的答案,目的是為了避免使用者在輸入完問題之前,就發送不必要的 Request。

<div id="app">
    <p>
        Ask a yes/no question:
        <input v-model="question">
    </p>
    <p>{{ answer }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            question: '',
            answer: 'I cannot give you an answer until you ask a question!'
        },
        watch: {
            // 如果 `question` 發生改變,這個函數就會運行
            question: function (newQuestion, oldQuestion) {
                this.answer = 'Waiting for you to stop typing...'
                this.debouncedGetAnswer()
            }
        },
        created: function () {
            this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
        },
        methods: {
            getAnswer: function () {
                if (this.question.indexOf('?') === -1) {
                    this.answer = 'Questions usually contain a question mark. ;-)'
                    return
                }
                this.answer = 'Thinking...'
                var vm = this
                axios.get('https://yesno.wtf/api')
                    .then(function (response) {
                        vm.answer = _.capitalize(response.data.answer)
                    })
                    .catch(function (error) {
                        vm.answer = 'Error! Could not reach the API. ' + error
                    })
            }
        }
    });
</script>

一開始我們還沒輸入問題的時候,它會跳出”I cannot give you an answer until you ask a question! 就是叫你趕快給我問問題喇

https://ithelp.ithome.com.tw/upload/images/20210929/20131400njZ89aY6zx.png

在打字的時候會跳出”Waiting for you to stop typing…”
https://ithelp.ithome.com.tw/upload/images/20210929/20131400GNtG7knQ3p.png

當我們打好字停下來,它會判斷有沒有問號,沒有的話會跟你說問問題要包含問號歐(´▽`ʃ♡ƪ)
https://ithelp.ithome.com.tw/upload/images/20210929/20131400IaJeezhdyn.png

打完問題(加上問號)他會先思考思考
https://ithelp.ithome.com.tw/upload/images/20210929/20131400scrA4sBgzu.png

看來它今天過得不太好இдஇ 沒事喇 我也不太好( ´・・)ノ(._.`)
https://ithelp.ithome.com.tw/upload/images/20210929/20131400voZwGp91qm.png

Computed VS Watch

<div id="app">
    <p>computed:{{ fullName }}</p>
    <p>watch:{{fullNameWatch}}</p>
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            firstName: 'Foo',
            lastName: 'Bar',
            fullNameWatch: 'Foo Bar' // watch 需手動設置初始值
        },
        computed: {
            fullName: function () {
                return this.firstName + ' ' + this.lastName;
            }
        },
        watch: {
            firstName: function (val) {
                this.fullNameWatch = this.firstName + ' ' + this.lastName;
            },
            lastName: function (val) {
                this.fullNameWatch = this.firstName + ' ' + this.lastName;
            }
        }
    });
</script>

我們可以看到兩者呈現的結果是一樣的
但watch的程式碼事命令式且重複,所以在這個例子中比要適合用computed,較精簡也較好懂(「・ω・)「
https://ithelp.ithome.com.tw/upload/images/20210929/20131400wdv36HSBw7.png


上一篇
Day 17. 計算屬性(Computed) VS 方法(Methods)
下一篇
Day 19. v-bind - Class的綁定
系列文
菜鳥學前端,一起vue起來 !30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言