淺談Vue3 Composition API如何替換Vue Mixins
想在你的Vue組件之間共享代碼?如果你熟悉Vue 2 則可能知道使用mixin,但是新的Composition API 提供了更好的解決方案。
在本文中,我們將研究mixins的缺點(diǎn),并了解Composition API如何克服它們,并使Vue應(yīng)用程序具有更大的可伸縮性。
回顧Mixins功能
讓我們快速回顧一下mixins模式,因?yàn)閷?duì)于下一部分我們將要講到的內(nèi)容,請(qǐng)務(wù)必將其放在首位。
通常,Vue組件是由一個(gè)JavaScript對(duì)象定義的,它具有表示我們所需功能的各種屬性——諸如 data,methods,computed 等。
// MyComponent.js export default { data: () => ({ myDataProperty: null }), methods: { myMethod () { ... } } // ... }
當(dāng)我們想在組件之間共享相同的屬性時(shí),可以將公共屬性提取到一個(gè)單獨(dú)的模塊中:
// MyMixin.js export default { data: () => ({ mySharedDataProperty: null }), methods: { mySharedMethod () { ... } } }
現(xiàn)在,我們可以通過將其分配給 mixin config屬性將其添加到任何使用的組件中。在運(yùn)行時(shí),Vue會(huì)將組件的屬性與任何添加的mixin合并。
// ConsumingComponent.js import MyMixin from "./MyMixin.js"; export default { mixins: [MyMixin], data: () => ({ myLocalDataProperty: null }), methods: { myLocalMethod () { ... } } }
對(duì)于這個(gè)特定的例子,在運(yùn)行時(shí)使用的組件定義應(yīng)該是這樣的:
export default { data: () => ({ mySharedDataProperty: null myLocalDataProperty: null }), methods: { mySharedMethod () { ... }, myLocalMethod () { ... } } }
Mixins被認(rèn)為“有害”
早在2016年中期,丹·阿布拉莫夫(Dan Abramov)就寫了《mixin被認(rèn)為是有害的》(mixin Considered Harmful),他在書中辯稱,將mixin用于在React組件中重用邏輯是一種反模式,主張遠(yuǎn)離它們。
不幸的是,他提到的關(guān)于React mixins的缺點(diǎn)同樣適用于Vue。在了解Composition API如何克服這些缺點(diǎn)之前,讓我們熟悉這些缺點(diǎn)。
命名沖突
我們看到了mixin模式如何在運(yùn)行時(shí)合并兩個(gè)對(duì)象。如果他們兩個(gè)都共享同名屬性,會(huì)發(fā)生什么?
const mixin = { data: () => ({ myProp: null }) } export default { mixins: [mixin], data: () => ({ // 同名! myProp: null }) }
這就是合并策略發(fā)揮作用的地方。這是一組規(guī)則,用于確定當(dāng)一個(gè)組件包含多個(gè)具有相同名稱的選項(xiàng)時(shí)會(huì)發(fā)生什么。
Vue組件的默認(rèn)(但可以配置)合并策略指示本地選項(xiàng)將覆蓋mixin選項(xiàng)。Vue組件的默認(rèn)(可選配置)合并策略指示本地選項(xiàng)將覆蓋mixin選項(xiàng)。不過也有例外,例如,如果我們有多個(gè)相同類型的生命周期鉤子,這些鉤子將被添加到一個(gè)鉤子數(shù)組中,并且所有的鉤子都將被依次調(diào)用。
盡管我們不應(yīng)該遇到任何實(shí)際的錯(cuò)誤,但是在跨多個(gè)組件和mixin處理命名屬性時(shí),編寫代碼變得越來越困難。一旦第三方mixin作為帶有自己命名屬性的npm包被添加進(jìn)來,就會(huì)特別困難,因?yàn)樗鼈兛赡軙?huì)導(dǎo)致沖突。
隱式依賴
mixin和使用它的組件之間沒有層次關(guān)系。這意味著組件可以使用mixin中定義的數(shù)據(jù)屬性(例如mySharedDataProperty),但是mixin也可以使用假定在組件中定義的數(shù)據(jù)屬性(例如myLocalDataProperty)。這種情況通常是在mixin被用于共享輸入驗(yàn)證時(shí)出現(xiàn)的,mixin可能會(huì)期望一個(gè)組件有一個(gè)輸入值,它將在自己的validate方法中使用。
不過,這可能會(huì)引起一些問題。如果我們以后想重構(gòu)一個(gè)組件,改變了mixin需要的變量的名稱,會(huì)發(fā)生什么情況呢?我們?cè)诳催@個(gè)組件時(shí),不會(huì)發(fā)現(xiàn)有什么問題。linter也不會(huì)發(fā)現(xiàn)它,我們只會(huì)在運(yùn)行時(shí)看到錯(cuò)誤。
現(xiàn)在想象一個(gè)有很多mixin的組件。我們可以重構(gòu)本地?cái)?shù)據(jù)屬性嗎?或者它會(huì)破壞mixin嗎?我們得手動(dòng)搜索才能知道。
從mixins遷移
mixin的替代方案,包括高階組件,utility 方法和其他一些組件組成模式。
mixins的缺點(diǎn)是Composition API背后的主要推動(dòng)因素之一,讓我們快速了解一下它是如何工作的,然后再看它如何克服mixin問題。
快速入門Composition API
Composition API的主要思想是,我們將它們定義為從新的 setup 函數(shù)返回的JavaScript變量,而不是將組件的功能(例如state、method、computed等)定義為對(duì)象屬性。
以這個(gè)經(jīng)典的Vue 2組件為例,它定義了一個(gè)“計(jì)數(shù)器”功能:
//Counter.vue export default { data: () => ({ count: 0 }), methods: { increment() { this.count++; } }, computed: { double () { return this.count * 2; } } }
下面是使用Composition API定義的完全相同的組件。
// Counter.vue import { ref, computed } from "vue"; export default { setup() { const count = ref(0); const double = computed(() => count * 2) function increment() { count.value++; } return { count, double, increment } } }
首先會(huì)注意到,我們導(dǎo)入了 ref 函數(shù),該函數(shù)允許我們定義一個(gè)響應(yīng)式變量,其作用與 data 變量幾乎相同。計(jì)算屬性的情況與此相同。
increment 方法不是被動(dòng)的,所以它可以被聲明為一個(gè)普通的JavaScript函數(shù)。注意,我們需要更改子屬性 count 的 value 才能更改響應(yīng)式變量。這是因?yàn)槭褂?ref 創(chuàng)建的響應(yīng)式變量必須是對(duì)象,以便在傳遞時(shí)保持其響應(yīng)式。
定義完這些功能后,我們將從 setup 函數(shù)中將其返回。上面兩個(gè)組件之間的功能沒有區(qū)別,我們所做的只是使用替代API。
代碼提取
Composition API的第一個(gè)明顯優(yōu)點(diǎn)是提取邏輯很容易。
讓我們使用Composition API重構(gòu)上面定義的組件,以使我們定義的功能位于JavaScript模塊 useCounter 中(在特性描述前面加上“use”是一種Composition API命名約定。)。
//useCounter.js import { ref, computed } from "vue"; export default function () { const count = ref(0); const double = computed(() => count * 2) function increment() { count.value++; } return { count, double, increment } }
代碼重用
要在組件中使用該函數(shù),我們只需將模塊導(dǎo)入組件文件并調(diào)用它(注意導(dǎo)入是一個(gè)函數(shù))。這將返回我們定義的變量,隨后我們可以從 setup 函數(shù)中返回它們。
// MyComponent.js import useCounter from "./useCounter.js"; export default { setup() { const { count, double, increment } = useCounter(); return { count, double, increment } } }
乍一看,這似乎有點(diǎn)冗長而毫無意義,但讓我們來看看這種模式如何克服了前面討論的mixins問題。
命名沖突解決了
我們之前已經(jīng)了解了mixin如何使用與消費(fèi)者組件中的名稱相同的屬性,或者甚至更隱蔽地使用了消費(fèi)者組件使用的其他mixin中的屬性。
這不是Composition API的問題,因?yàn)槲覀冃枰@式命名任何狀態(tài)或從合成函數(shù)返回的方法。
export default { setup () { const { someVar1, someMethod1 } = useCompFunction1(); const { someVar2, someMethod2 } = useCompFunction2(); return { someVar1, someMethod1, someVar2, someMethod2 } } }
命名沖突的解決方式與其他任何JavaScript變量相同。
隱式依賴…解決了!
前面還看到mixin如何使用在消費(fèi)組件上定義的 data 屬性,這可能會(huì)使代碼變得脆弱,并且很難進(jìn)行推理。
合成函數(shù)(Composition Function)還可以調(diào)用消費(fèi)組件中定義的局部變量。不過,不同之處在于,現(xiàn)在必須將此變量顯式傳遞給合成函數(shù)。
import useCompFunction from "./useCompFunction"; export default { setup () { // 某個(gè)局部值的合成函數(shù)需要用到 const myLocalVal = ref(0); // 它必須作為參數(shù)顯式地傳遞 const { ... } = useCompFunction(myLocalVal); } }
總結(jié)
mixin模式表面上看起來很安全。然而,通過合并對(duì)象來共享代碼,由于它給代碼增加了脆弱性,并且掩蓋了推理功能的能力,因此成為一種反模式。
Composition API最聰明的部分是,它允許Vue依靠原生JavaScript中內(nèi)置的保障措施來共享代碼,比如將變量傳遞給函數(shù)和模塊系統(tǒng)。
這是否意味著Composition API在各方面都比Vue的經(jīng)典API優(yōu)越?不是的。在大多數(shù)情況下,你堅(jiān)持使用經(jīng)典API是沒有問題的。但是,如果你打算重用代碼,Composition API無疑是優(yōu)越的。
到此這篇關(guān)于淺談Vue3 Composition API如何替換Vue Mixins的文章就介紹到這了,更多相關(guān)Vue3 Composition 替換Vue Mixins內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Vue2的移動(dòng)端開發(fā)環(huán)境搭建詳解
這篇文章主要給大家介紹的是基于Vue2的移動(dòng)端環(huán)境搭建,移動(dòng)端大家更多想到的是響應(yīng)布局,我們根據(jù)不同大小的屏幕進(jìn)行適配,當(dāng)然少不了我們的重頭戲rem,移動(dòng)端相比pc端就沒什么特別的了。我會(huì)一步一步帶領(lǐng)大家進(jìn)入Vue2的世界,感興趣的朋友下面來一起學(xué)習(xí)學(xué)習(xí)吧。2016-11-11Vue前端如何設(shè)置Cookie和鑒權(quán)問題詳解
這篇文章主要介紹了前端如何設(shè)置和使用Cookie,并對(duì)比了Cookie和Token在鑒權(quán)中的優(yōu)缺點(diǎn),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02Vuex中mutations與actions的區(qū)別詳解
下面小編就為大家分享一篇Vuex中mutations與actions的區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03VUE利用vuex模擬實(shí)現(xiàn)新聞點(diǎn)贊功能實(shí)例
本篇文章主要介紹了VUE利用vuex模擬實(shí)現(xiàn)新聞點(diǎn)贊功能實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06Vue3的動(dòng)態(tài)組件使用場(chǎng)景與示例
在 Vue 中,組件是構(gòu)建用戶界面的基礎(chǔ),而動(dòng)態(tài)組件的引入,更是讓開發(fā)者能夠在應(yīng)用中實(shí)現(xiàn)靈活、可重用的視圖邏輯,本文將探討 Vue 3 中的動(dòng)態(tài)組件,分享其使用場(chǎng)景,并通過示例代碼來說明其操作方法,需要的朋友可以參考下2025-01-01