iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
3
Modern Web

超緊繃!30天Vue.js學習日記系列 第 9

[Vue.js][日記]監聽屬性&計算屬性

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20190912/20110850dsypfXRkNe.jpg

超緊繃!30天Vue.js學習日記 監聽屬性&計算屬性

大家好,今天我要介紹的是Vue中的監聽屬性(watch)以及計算屬性(computed),並且參考官網做一個簡單的比較,然後標題的部分比較正常單純只是因為我沒梗了XD

  • 計算屬性(computed)

在模板語法中,是允許我們在雙括號內做一些簡單的邏輯運算的,不過,若放入太多的邏輯會使我們難以去維護模板:

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

因此,計算屬性就出現了,我們可以將任何複雜的邏輯都放入計算屬性當中:

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
<script>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 計算屬性的getter
    reversedMessage: function () {
      // `this` 指向 vm 實例
      return this.message.split('').reverse().join('')
    }
  }
})
</script>

在上述範例中,只要message的值改變, reversedMessage()就會重新執行一次。

當然,我們同樣可以使用methods去做出同樣的效果:

methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

雖然在這邊看不出差別,不過實際上,methods與computed有著不小的差異:
Computed會將計算結果做緩存,當相依的資料改變時,Computed才會再次計算,而methods則不同,只要綁定的物件重新渲染,它就會再次計算,即使function內相依的值沒有改變也是一樣,對於簡單的組件可能沒差,但是假設今天我們使用的function計算出的結果相依於其他的計算屬性,這樣一來一往,就會有巨大的性能差異!

  • 監聽屬性(watch)

若我們希望資料a變動時,資料b也做出相對應的變動,我們可能就會使用監聽屬性,但是在這邊,官方文件告訴我們不要濫用它,要多多使用計算屬性。
以此為範例:

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

若我們使用watch:

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
    }
  }
})

若我們在這邊使用Computed則可以少打不少的code,畢竟上面的兩個function基本上是一樣的。

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

高下立判(茶)

不過官方也有提到,watch也不是如此不堪,若我們今天要訪問一個API,並在等待過程中設置一個等待狀態,我們就必須使用watch,這邊一樣引用官網提供的code:

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!—-因為 AJAX 和通用工具的發展已經相當成熟,Vue 核心代碼沒有重複-->
<!--提供這些功能以保持精簡。我們也可以使用自己熟悉的工具。 -->
<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 watchExampleVM = new Vue({
  el: '#watch-example',
  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 () {
    // `_.debounce` 是一個透過 Lodash 限制操作频率的函式。
    // 在這個例子中,我们希望限制user訪問 yesno.wtf/api 的频率
    // AJAX 請求直到用戶輸入完畢才會送出。
    // 相關補充:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = '不打問號的話還是個問句嗎?'
        return
      }
      this.answer = '讓我想想...'
      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>

上述的範例有使用到axios,不過在這裡我們把重點放在watch的功用,axios在遙遠的未來…會提到的XDD

貼心如我,在這邊一樣提供本日範例供讀者下載:

https://drive.google.com/open?id=17WA7LlMGgMxwBSylRwAFc8iyPwsafUwB

今天的介紹就到這邊結束,我們明天見啦!掰掰~


上一篇
[Vue.js][日記]組件在蓋,基礎手法要有!
下一篇
[Vue.js][日記]class與style綁定
系列文
超緊繃!30天Vue.js學習日記33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言