iT邦幫忙

2021 iThome 鐵人賽

DAY 9
2
Modern Web

[ 重構倒數30天,你的網站不Vue白不Vue ] 系列 第 9

[重構倒數第22天] - 減少 watch,改用 computed

  • 分享至 

  • xImage
  •  

前言

該系列是為了讓看過Vue官方文件或學過Vue但是卻不知道怎麼下手去重構現在有的網站而去規畫的系列文章,在這邊整理了許多我自己使用Vue重構很多網站的經驗分享給讀者們。

mike vue

我們開發的時候常常會需要監控資料的變化,提到資料的監控很多人第一個反應都會想到使用 watch這個方法來監控資料,然後當資料改變的時候再做些什麼事情,我們可以先來看看以下這個範例。

首先我新增了一個 contentText的資料,然後在它 onMounted去執行 setTimeout讓它一秒後改變裡面的 value 。

const { createApp, ref, watch, onMounted } = Vue;
const App = {
  setup(){
    const contentText = ref("home")
    
    onMounted(()=> {
      setTimeout(()=> {
        contentText.value = "about"
      }, 1000)
    })
    return {
      contentText
    }
  }
}

然後我會把這個 contentText 當成 props 傳下去我的子組件

<div id="app">
  <conetnt-bar :styletype="contentText"></conetnt-bar>
</div>

我們來看一下子組件

app.component('conetnt-bar', {
  props: {
    styletype: {
      type: String,
      default: ''
    }
  },
  setup(props){
    const text = ref("")
    
    const handleType = (styletype) =>{
      if(styletype === 'home'){
        text.value = "首頁"
      }
      if(styletype === 'about'){
        text.value = "關於我們"
      }
    }
    
    watch(()=>props.styletype, (newVal)=> {
      handleType(newVal);
    })
    
    onMounted(()=> {
      handleType(props.styletype);
    })
    
    return {
      props,
      text
    }
  },
  template: `
    <h1>{{ text }}: {{props.styletype}}</h1>
  `
})

我們來理解一下這邊所做的事情

  1. 首先一開始的時候會我會在 onMounted地方去檢查 props 傳下來的 styletype 是什麼,然後改變相對應的文字。
  2. 如果今天傳下來的 styletype 被更改了,我會再透過 watch去監控 props 的改變,然後一樣去判斷,然後改變相對應的文字。

codepen範例 : https://codepen.io/MikeCheng1208/pen/OJmdNzO

我們在開發上面很長就會有像是這樣子類似的開發方式,需要去監控資料是否有改變,說老實話這個邏輯沒有錯,也的確可以這樣做,但是像是現在看到的這個範例,他其實可以不用到 watch,因為在我看過很多這種重構類型的專案,大部分都太濫用 watch 了,其實有一個東西叫做 computed,我稍微跟大家介紹一下 computed

computed 是一個計算屬性,設計它的初衷是用於簡單運算的,在模板中放入太多的邏輯會讓模板過重且難以維護,所以會需要透過computed 來重新處理過那些複雜的資料,官方文件有提到說

computed 屬性是基於Vue綁定的資料依賴關係緩存的

這意味者 computed 只在透過Vue綁定的資料發生改變時它們才會重新去執行處理計算,所以今天你的資料只要是Vue綁定的資料,都可以被計算處理過。

我們來看這邊改過後的例子:

const { createApp, ref, computed, onMounted } = Vue;

// ------

app.component('conetnt-bar', {
  props: {
    styletype: {
      type: String,
      default: ''
    }
  },
  setup(props){
    
    const text = computed(()=> {
      if(props.styletype === 'home') return "首頁"
      if(props.styletype === 'about') return "關於我們"
      return ''
    })
    
    return {
      props,
      text
    }
  },
  template: `
    <h1>{{ text }}: {{props.styletype}}</h1>
  `
})

codepen範例 : https://codepen.io/MikeCheng1208/pen/bGWzwNd

在這邊你會看到我拿掉了 ref 以及 watch 兩個方法,只載入了 computed ,透過 computed 我們可以更加簡單的去重組我們的資料,減少不比要的邏輯,只需要透過資料之間的重組,來產生出新的資料,而且只要 computed 內的資料沒有改變,就不會觸發重新 render,這就是 緩存,使用computed 的好處。

我們為什麼需要緩存?假設我們有一個性能開銷比較大的計算屬性 list,它需要遍歷一個巨大的數組並做大量的計算。然後我們可能有其他的計算屬性依賴於 list。如果沒有緩存,我們將不可避免的多次執行 list 的 getter!如果你不希望有緩存,請用 method 來替代。
參考官方文件:https://v3.vuejs.org/guide/computed.html

還有許多例子,例如我們會利用 watch 監聽 vue-router,看它的網址有沒有被改變,然後去改變畫面上的某的資料或是狀態,我們在 vue-router 的官方文件上面會看到這樣用法的例子

import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'

export default {
  setup() {
    const route = useRoute()
    const activeClass = ref('')

    watch(() => route.params.id, (newId) => {
        activeClass.value = `active-${newId}`
    })
    
    return { activeClass }
  },
}

但是如果使用 computed 就可以改成這樣子

import { computed } from 'vue'
import { useRoute } from 'vue-router'

export default {
  setup() {
    const route = useRoute()
    const activeClass = computed(()=> `active-${route.params.id}`)
    return { activeClass }
  },
}

你會發現少了很多的 code,變得簡單很多,還有很多開發上面 watch 都可以改成 computed 的例子,現在你了解到了 computed 的美好,今天開始就開始嘗試使用 computed 吧~

最後

開發上面雖然是先求有再求好,但是當有多餘的時間的時候,可以在回過頭來看一下哪邊可以來優化的,只要多練習幾次,以後就會在開發中越來越精準的使用,基本上這樣也可以減少發生問題的機率了。

好啦~今天就到這邊啦,有想到其他要補充的我會在打上來,明天見!

Mike Vue

那如果對於Vue3不夠熟的話呢?

Ps. 購買的時候請登入或註冊該平台的會員,然後再使用下面連結進入網站點擊「立即購課」,這樣才可以讓我獲得更多的課程分潤,還可以幫助我完成更多豐富的內容給各位。

我有開設了一堂專門針對Vue3從零開始教學的課程,如果你覺得不錯的話,可以購買我課程來學習
https://hiskio.com/bundles/9WwPNYRpz?s=tc

那如果對於JS基礎不熟的朋友,我也有開設JS的入門課程,可以參考這個課程
https://hiskio.com/bundles/b9Rovqy7z?s=tc

訂閱Mike的頻道享受精彩的教學與分享

Mike 的 Youtube 頻道
Mike的medium
MIke 的官方 line 帳號,好友搜尋 @mike_cheng


上一篇
[重構倒數第23天] - Tab 的 page 加入 router
下一篇
[重構倒數第21天] - 五種重構Vue2專案的時候最常看到需要被改善的code
系列文
[ 重構倒數30天,你的網站不Vue白不Vue ] 32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言