[Vue] 那就來寫前端吧 Vue 2 extends And Vue 3

by Mesak

開始寫專案之前,團隊都是使用 Vue 2 寫畫面,Vue 2 要升級到 Vue 3 對我來說,最大的轉變就是 extends 了

Vue 2 用的是 Options API, Vue 3 寫的是 Composition API,寫法什麼的對還沒開始完成專案的我來說,好像沒太大差異。

但是當我實際開始寫之後,才知道我在專案上之前應用了很多 extends 用法,在 Vue 3 裡面通通失效了…

原本寫成 extends 的作法是讓每個 Component 都可以不必撰寫就有此方法,data 也可以逐一傳遞,現在通通要改成 Vue 3 的寫法。

先來看看 原本的 Vue 2 實現方式:

export default {
  name: 'Base',
  components: {},
  data: function () {
    return {
      showQueryParam: false, 
      primaryKey: 'id', 
      pageInfo: {}, 
      resource: new Map()
    }
  },
  computed: {
    list: {
      get: function () {
        return Array.from(this.resource.values())
      },
      set: function (newData) {
        let resource = new Map()
        Array.from(newData, (value, _key) => {
          resource.set(value[this.primaryKey], value)
        })
        this.resource = resource
      },
    },
  },
  methods: {
    setStandardResult(result) {
      const { data, current_page, last_page, total, per_page } = result
      this.list = data
      this.pageInfo = { currentPage: current_page, lastPage: last_page, total: total, perPage: per_page }
    },
  }
}

原本我在 Vue 2 的寫法,後面只要元件使用 extends : Base ,那就會有內建的 data 數值,以及 methods ,還有 computed,這些參數都打好了,只需要 呼叫 API 的時候,使用 setStandardResult 把 laravel 內建的 paginate 取回,就可以很快的去設定 清單、分頁等內容,這些元件都可以持續的傳遞到 Pagination 元件或是 Table 元件等,要共用 function 就非常快速。

利用上述的 extends 方法,用 bootstrap vue 建立 sandbox 操作 建議開新頁看結果

現在專案要從 Vue 2 改成 Vue 3 ,讓我思考許久,看了許多參考文件,其中一個 Composition API 讓我感受到共用 function 的可能性。

就是 import 之後抽離 function 與 data ,並解構賦值,如此一來可以把預設的 data 塞到每個 Component 元件中,這邊簡單的說明

    getStandardResource() {
      const getData = () => {
        return reactive({
          primaryKey: 'id',
          resource: new Map(),
          pageInfo: {
            disable: false,
            page: 1,
            pageSize: 10,
            total: 0
          },
          list: computed({
            get: () => Array.from(pageData.resource.values()),
            set: (newData) => {
              let resource = new Map()
              Array.from(newData, (value, _key) => {
                resource.set(value[pageData.primaryKey], value)
              })
              pageData.resource = resource
            }
          })
        })
      }
      const pageData = getData()
      const setStandardResult = (response) => {
        const { current_page, last_page, total, per_page, data } = response
        pageData.pageInfo = { current_page, last_page, total, per_page, disable: false }
        pageData.list = data
      }
      return {
        pageData,
        setStandardResult
      }
    }

這段程式碼可以放在任一個要引入的地方,接著在你的 Component 裡面引入這隻檔案。

const { pageData, setStandardResult } = getStandardResource()

pageData 就是你預設的數值,你可以在 setup 裡面 return { …toRefs(pageData) } 把裡面每個變數響應到 template 中 setStandardResult 這個可以放到 methods 裡面,每次 call 完 API 去呼叫給值,這樣又可以異動原本的 pageData 數值,又不會跟其他 Component 的 pageData 汙染,Pagination 元件可以接受 pageInfo props 去顯示畫面,接收 emit 參數去異動 pageData 數值往後端發送。

利用上述的概念,用 quasar 2 建立出來的 sandbox 範例 建議開新頁看結果

主要應用在 /src/pages/Index.vue ,引入 /src/pages/base.js,當你有多頁相同 function 要共用的時候,可以利用 base.js 載入

每次應用相同的參數,來產生 Pagination Table 的元件所需的資料。

這種共用方式其實會來的比 Vue 2 還方便,可以把 function 拆分成你想要的組件,在資料的傳遞與改動數值如果在原始的 function 不好操作 ,建議改在原本的 Component 做就可以了,要不要轉換成共用的 function 可以視專案的程式碼的重複性質來引用。

以 Vue 2 的模式,就像是繼承一個血統一樣,父層有的基因繼承後的組件都會有,有些 data 你可能用不到,他會占用在你的實體中,但是這些 data 跟 method 你都可以用,或是被使用, Vue 3 的模式就像是捏臉系統一樣,你要從各個地方拿組件回來組回五官,但是你有可能組回來的東西會蓋過其他組件,所以在程式裡面撰寫者的掌握技術就很重要。

You may also like