Vue3 Composition API如何替换Vue Mixins


想在你的Vue组件之间同享代码?假如你了解Vue 2 则可能知道运用mixin,可是新的Composition API 提供了更好的处理方案。

在本文中,咱们将研究mixins的缺陷,并了解Composition API怎么战胜它们,并使Vue应用程序具有更大的可7 ] B M G C n D伸缩性。z S K e @ B g

回忆Mixins功用

让咱们快速回忆一下mixins形式,由于关于下一部分咱们将要讲到的内容,请有必要将其放在首位。

通常,Vue组件是由一个JavaScript目标界说的,它具有表明咱们z k z所需功用的各种特点——诸o A i E _ rdatamethodscomputed 等。

// MyComponent.js
export default {
data; 5 h J , . o A: () => ({
myDataProperty: null
}),
methods: {
myMethod () { ... }
}
// ...
}

当咱们想在组件之F m & m I v间同享相同的特点时,能够将公共特点提取到一个独自的模块中:

// MyMixin.js
exporx e 2 W 8 7 mt default {
das v W | O Mta: () => ({
mySh~ #  1 J m jaredDataProperty: null
}),
methods: {
mySharedMethod () { ... }
}T y ] @
}

现在,咱们能够通过将其分配给 mixin config特点将其增Q k / ] T o R加到任何运用的组件中。在运行时,Vue会将组件的特点与任何增加的mixin兼并。

// ConsumingComponent.js
imp z D d | Zort MyMixin from "./MyMixin.js9 { J d 0 +";
export default {
mixins: [MyMixin],
data: () => ({
myLocalDataProperty: null
}),
methods: {
myLocalMethod () { ... }
}
}

关于这个特定的比如,. Z ) ? ]在运行时运用的组件界说应该是这样的:

exportN j n = n default {
data: () => ({
mySharedDataProperty: null
myLocalDataProperty: null
}),
methods: {
mySharedMethod () { ... }, { p 5 5 r Z,
myLocalMethod () { ... }
}
}

Mixins被认为“有害”

早在2016年中期,丹阿布拉莫夫(Dan Abramov)就写了《mixi( / @ N `n被认为是有害的》(mixin Considered Harmful),他在书0 ; ( 4 D ? j 0 A中辩称,将mixin用于X w [ $ * L f _在ReB U Y ! Fact组件中重用逻辑是一种反形式,建议远离它们。

不幸的是U ] F w X R n,他说到的关于React mixins的缺陷同样适用于6 Q vVue。在了解Composition API怎么战胜这些缺陷之前,让咱们了解这些缺陷。

命名抵触

咱们看到了mix? t N B { j 5 Rin形式怎么在运行时兼并两个目标。假如他们两个都同享同名特点,会发作什么?

const mixin =4 t r {
data: () => ({
myProp: null
})
}j A g L Q & /
export default {
mixins: [mixin],
data: () => ({
// 同名!
myProp: null
})
}

7 h * N o O就是兼并战略发挥效果的当6 5 k ^ & , l地。这是一组规矩,用于确定当一个组件包括多个具有相同称号的选项时会发作什么。

Vue组件的默许(但能够装备)兼并战略指示本地选项将掩盖mixin选项。Vue组件的默许(可选装备)兼并战略指示本地选项将掩盖mixin选项。不过也有例外,例如,假如咱们有多个相同类型的生命周期钩子,这些钩子将被增加到一3 H q & @ / ~ n个钩子数组中,而且一切的钩子都n V T 1 X M将被依次调用。

尽管咱们不应该遇到任何实践的错误,可是在跨多个组件和mixin处理命名特点时,编写代码变得越来越困难。一旦第三方mixin作为带有自己命名特点的npmA G = y 2 z k q包被增加进来,就会特别困难,y 0 D m B ! 6 m T由于! ; [ E b Q它们可能会导致抵触。

隐式依赖

mixin和运用它的组件之间没有层次关系。这意味5 q g 2着组件能够运用mixin中界说的数据特点(例如mySha * $ Y b Y o ~ AredDataPropeW c 3 n k prtyv v y),可是mixin也能够运用假定在组件中界说的数据特点(例如myLocalDataProperty)。这种状况通常是在mixin被用于d Y V同享T q I M p ~输入验证时出现的,mixin可能会希望一个组件有一个输入值,它将在自己的validate办法中运用。

不过,这可能会引起一些问题。假如咱们以后想重构一个组件,改变了mixin需求的变量的称号,会发作什么状况呢?U – 1咱们在看这个组件时,不会发现有什么问题。linter也不会发现它,咱们只会在运行时看到错误。

现在想象一个有很多mixin的组件。咱们能够重构本地数据特点吗?或者它会破坏mixin吗?咱们得手动搜索才干Q x y = g $ s %知道。

从mixins搬迁

mixin的代替方案,包括高阶组件,utility 办法和其他一些组件组成形式。

mixins的缺陷是Composition API背面的首要推动要素之一,让咱们快速了解一下它是怎么工作的,然后再看它怎么战胜mixin问题。

快速入门Compositiok V q i U 6 K . ^n API

Composition API的首要思维是,咱们将9 1 F (它们界说为重新的 setup 函数回来的JavaScript变量,而不是将组件的功用(例如state、method、computed等)界说为目标特点。

以这个经典的Vue 2组件为例,它界说了一个“计数器”功用:

//Counter.vue
export default {
data: () =[ N / l N => ({
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 =y g R V / I computed(()$ O 4 =&~ % w d } 5 4 1gt; count * 2)
function increment() {
count.value++;
}
return {
count,
double,
increment
}
}
}

首先会留意到,咱们导入了 ref 函数,该函数允许咱们界说一个呼应式变量,其效果与 data 变量简直相同。核算特点的状况与此相同。

increment 办法不是T g Z U T被动的,所以它能够被声明为一个普通的JavaScript函数。留意,咱们h K a r G y需求更改子特点 countvalue 才干更改呼应式变量。这是由于运用 r: 0 5 x def 创建的呼应式变量有必要是目标,以便在传递时保持其呼应式。

界说完这些功用后,咱们将从 setup 函数中将其回来。上面两个组件之间的功用没有差异,咱们所做的只是运用代替API。

代码提取

Composition A] 7 f – KPIs R 3 n o + t的第一个显着优点是提取逻辑很简单。

让咱们运用Composition API重构上面界说的组件w g # ^,以使咱们界说的功用位于JavaScript模块 useCounter 中(在特性描述前面加上“use”是一种Composition API命名约定。)。

/i 3 8 @ C 6 p g/useCounter.js
import { ref, computed } from "vue";
export default function () {
const count = ref(0);
const dou) A ~ $ o ; h ? ble = computed(() => co / C [ k S s &unt * 2)
function incremen* N = y ` o t() {
count.value++;
}I = # x O n 4 J
return {
count| ` n . N 4,
double,
increment
}
}

代码重用

要在组件中运用该函数,咱们只& P Y 0 d 4需将o q p X r V : r [模块导入组件文件并调用它(留意导入是一个函数)。这将回来咱们界说的变量,随后咱们能够从 setup 函数中回来它们。

// MyCompon8 C : o lent.js
importW s q c 6 } useCounter from "./useB 9 J 8 4Counter.js";
export1 o - default {
setup() {
const { count, douc 1 W n p *ble, increment } =/ z / * ! y % useCounter();
return {
count,
double,
increment
}
}
}

乍一看,这似乎有点冗长而毫无意义,但让咱L 6 j {们来看看这种形式怎么战胜了前面讨论的mixins问题。

命名抵触处理了

咱们之前已经了解了mixin怎么运用与顾客组件中的称号相同的特点,或者乃至更荫蔽| F V H % Y u ]地运用了顾客组件运用的其他mixin中的特点。

这不是Composition API的问题,由于咱们需求显式命名任何状态或从合成函数回来的办法。

export default {
setup () {
cd O * [ t # 9 c &onst { someVa7 7 H | T ; qr1, someMethod1 } = useCompFunction1();
const { someVar2, someMethod2 } = useCompFunction2();
return {
someVar1,
someM? g ^ K Z :ethod1,
someVar2,
someMethod2
}
}
}

命名抵触的处理方式与其他任何JavaScript变量相J . d O v ( G同。

隐式依赖…处理了!1 I f

前面还看到mixin怎$ [ | | , Z O v t么运用在消费组件上界说的 data 特点,这可能会使代码变得脆弱,而且很难进行推理。

合成函数(Composition FP s } L 8 ; e S Dunction)还能够调用消费组件中界说的局部变量。不过,不同之处在于,现在有必要将此变量显式传递给合成函数。

import useCompFunction from "./useCompFunction";
export default {
setup () {
// 某个局部U O 8 L值的合成函数需求用到
const myLocalVal = ref(0);
// 它有必要作为参数显式地传递
const {L 3 7 L [ f $ m C ... } = useCompFunction(myLocalVal);
}
}

总结

mixin形式表面上看起来很安全。然而,通过兼并目标来同享代码,` ~ h k N N { L ]由于它给代码增加了脆弱性,而且掩盖了推理功用的能力,4 1 t g 9 Q o 6 –因而成为一种反形式。

Composition API最聪明的部分是,它允许Vue依靠原生JavaScript中内置的保障办法来同享代码,比如将变量传递给函数和模块体系。

这是否意味着Composition API在各方面都比Vue的7 . D U经典API优胜?不是的。在大多数状况下,你坚持运用经典API是没有问题的。可是,假如你计划重用代码,Composition API无疑是优胜的。


原文:c( h q gss-tricks.com/how-the-vue…

作者:Anthony Gore

Vue3 Composition API如何替换Vue Mixins

发表评论

提供最优质的资源集合

立即查看 了解详情