高階 vue 元件模式 2

HaoliangWu發表於2018-10-21

02 編寫複合元件

目標

我們需要實現的需求是能夠使使用者通過 <toggle> 元件動態地改變包含在它內部的內容。

熟悉 vue 的童鞋可能馬上會想到不同的解決方案,比如使用 slot 並配合 v-if,我們這裡採用另外一種方法,利用 vue 提供的 provide/inject 屬性按照複合元件的思想來實現。

這裡簡單介紹下 provide/inject 的功能,它允許某個父元件向子元件注入一個依賴項(這裡的父子關係可以跨域多個層級,也就是祖先與後代),如果我們在其他 mvvm 框架對比來看的話,你可以發現其他框架也具有相同的特性,比如:

  • angularjs: directive 中的 require 屬性來宣告注入邏輯
  • Angular: 依賴注入中元件級別的注入器
  • React: context 上下文物件

想進一步瞭解的話,可以參考官方文件

實現

在 vue 中,這裡我們會分別實現三個元件,依次為:

  • toggle-button: 代表開關,用來渲染父元件的開關狀態
  • toggle-on: 根據父元件 toggle 的開關狀態,渲染當狀態為時的內容
  • toggle-off: 根據父元件 toggle 的開關狀態,渲染當狀態為時的內容

在上一篇文章中,我們已經實現了 toggle 元件,這裡我們要做一些更改。首先,需要使用 provide 屬性增加一個提供依賴的邏輯,如下:

provide() {
    return {
      toggleComp: {
        status: this.status,
        toggle: this.toggle
      }
    }
}
複製程式碼

這裡的 status 是該元件 data 中的宣告的一個可監聽物件,這個物件包含一個 on 屬性來代表元件的開關狀態,而 toggle 則是 methods 中的一個元件方法。

關於為什麼這裡不直接使用 on 屬性來代表開關狀態,而使用一個可監聽物件,是因為 provideinject 繫結並不是可響應的,同時官方文件也指出,這是刻意而為,所以為了享受到 vue 響應性帶來的便利性,我們這裡傳入 status 這個可監聽物件。

對於其他三個元件,其內部實現邏輯十分簡單,相信讀者通過參考線上程式碼例項馬上就能看懂,這裡只提一下關於 inject 宣告注入依賴的邏輯,如下:

inject: { toggleComp: "toggleComp" }
複製程式碼

這裡的 "toggleComp" 與之前的 provide 物件中宣告的 key 值所對應,而 inject 物件的 key 值當前元件注入依賴項的變數名稱,之後,子元件即可以通過 this.toggleComp 來訪問父元件的屬性與方法。

成果

通過複合元件的方式,我們將 toggle 元件劃分為了三個更小的、職責更加單一的子元件。同時由於 toggle-ontoggle-off 都使用 slot 來動態地注入元件呼叫者在其內部包含的自定義渲染邏輯,其靈活性得到了進一步的提升,只要這三個元件是作為 toggle 元件的子元件來呼叫,一切都將正常執行。

你可以下面的連結來看看這個元件的實現程式碼以及演示:

總結

通常情況下,在設計和實現職能分明的元件時,可以使用這種模式,比如 tabstab 元件,tabs 只負責 tab 的滾動、導航等邏輯,而 tab 本身僅負責內容的渲染,就如同這裡的 toggletoggle-button、``toggle-ontoggle-off` 一樣。

目錄

github gist

相關文章