1. 程式人生 > >Vue.js 元件複用和擴充套件之道

Vue.js 元件複用和擴充套件之道

軟體程式設計有一個重要的原則是 D.R.Y(Don't Repeat Yourself),講的是儘量複用程式碼和邏輯,減少重複。元件擴充套件可以避免重複程式碼,更易於快速開發和維護。那麼,擴充套件 Vue 元件的最佳方法是什麼? Vue 提供了不少 API 和模式來支援元件複用和擴充套件,你可以根據自己的目的和偏好來選擇。 本文介紹幾種比較常見的方法和模式,希望對你有所幫助。 * * * ## 擴充套件元件是否必要 要知道,所有的元件擴充套件方法都會增加複雜性和額外程式碼,有時候還會增加效能消耗。 因此,在決定擴充套件元件之前,最好先看看有沒有其他更簡單的設計模式能完成目標。 下面幾種元件設計模式通常足夠替代擴充套件元件了: * `props` 配合模板邏輯 * slot 插槽 * JavaScript 工具函式 #### `props` 配合模板邏輯 最簡單的方法是通過`props`結合模板條件渲染,來實現元件的多功能。 比如通過 `type` 屬性: *MyVersatileComponent.vue* ``` ``` 使用元件的時候傳不同的`type`值就能實現不同的結果。 ``` // *ParentComponent.vue* ``` 如果出現下面兩種情況,就說明這種模式不適用了,或者用法不對: 1. 元件組合模式把狀態和邏輯分解成原子部分,從而讓應用具備可擴充套件性。如果元件記憶體在大量條件判斷,可讀性和可維護性就會變差。 2. props 和模板邏輯的本意是讓元件動態化,但是也存在執行時資源消耗。如果你利用這種機制在執行時解決程式碼組合問題,那是一種反模式。 #### slot(插槽) 另一種可避免元件擴充套件的方式是利用 [slots(插槽)](https://vuejs.org/v2/guide/components-slots.html),就是讓父元件在子元件內設定自定義內容。 ``` // *MyVersatileComponent.vue* ``` ``` // *ParentComponent.vue* ``` 渲染結果: ```

Common markup

Inserting into the slot

``` 這種模式有一個潛在約束, slot 內的元素從屬於父元件的上下文,在拆分邏輯和狀態時可能不太自然。`scoped slot`會更靈活,後面會在無渲染元件一節裡提到。 #### JavaScript 工具函式 如果只需要在各元件之間複用獨立的函式,那麼只需要抽取這些 JavaScript 模組就行了,根本不需要用到元件擴充套件模式。 JavaScript 的模組系統是一種非常靈活和健壯的程式碼共享方式,所以你應該儘可能地依靠它。 *MyUtilityFunction.js* ``` export default function () { ... } ``` *MyComponent.vue* ``` import MyUtilityFunction from "./MyUtilityFunction"; export default { methods: { MyUtilityFunction } } ``` ## 擴充套件元件的幾種模式 如果你已經考慮過以上幾種簡單的模式,但這些模式還不夠靈活,無法滿足需求。那麼就可以考慮擴充套件元件了。 擴充套件 Vue 元件最流行的方法有以下四種: * [Composition 函式](https://vuejsdevelopers.com/2017/06/11/vue-js-extending-components/#composition-functions) * [mixin](https://vuejsdevelopers.com/2017/06/11/vue-js-extending-components/#mixins) * [高階元件(HOC)](https://vuejsdevelopers.com/2017/06/11/vue-js-extending-components/#higher-order-components) * [無渲染元件](https://vuejsdevelopers.com/2017/06/11/vue-js-extending-components/#renderless-components) 每一種方法都有其優缺點,根據使用場景,或多或少都有適用的部分。 ## Composition API 元件之間共享狀態和邏輯的最新方案是 Composition API。這是 Vue 3 推出的 API,也可以在 Vue 2 裡當外掛使用。 跟之前在元件定義配置物件裡宣告`data`,`computed`,`methods`等屬性的方式不同,Composition API 通過一個 `setup` 函式宣告和返回這些配置。 比如,用 Vue 2 配置屬性的方式宣告 *Counter* 元件是這樣的: *Counter.vue* ```