写点什么

Vue3 Composition API 如何替换 Vue Mixins

用户头像
志学Python
关注
发布于: 2020 年 07 月 08 日
Vue3 Composition API如何替换Vue Mixins

想在您的 Vue 组件之间共享代码?如果您熟悉 Vue 2,则可能已为此目的使用了 mixin。但是新的 Composition API(现在可以作为 Vue 2 的插件和 Vue 3 的即将发布的功能使用)提供了更好的解决方案。

在本文中,我们将研究 mixins 的缺点,并查看 Composition API 如何克服它们,并使 Vue 应用程序具有更大的可伸缩性。

简而言之

让我们快速回顾一下 mixins 模式,因为对于下一部分将要介绍的内容,请务必将其放在首位。

之类的东西-通常情况下,Vue 公司的组件用 JavaScript 对象与代表我们所需要的功能的各种属性定义 data,methods,computed,等等。

// MyComponent.jsexport default {  data: () => ({    myDataProperty: null  }),  methods: {    myMethod () { ... }  }  // ...}
复制代码


当我们想在组件之间共享相同的属性时,可以将公共属性提取到一个单独的模块中:

// MyComponent.jsexport default {  data: () => ({    myDataProperty: null  }),  methods: {    myMethod () { ... }  }  // ...}
复制代码


现在,我们可以通过将其分配给 mixinconfig 属性,将其添加到任何使用的组件中。在运行时,Vue 会将组件的属性与所有添加的 mixin 合并。

// ConsumingComponent.jsimport MyMixin from "./MyMixin.js";

export default { mixins: [MyMixin], data: () => ({ myLocalDataProperty: null }), methods: { myLocalMethod () { ... } }}
复制代码


对于此特定示例,运行时使用的组件定义如下所示:


export default {  data: () => ({    mySharedDataProperty: null    myLocalDataProperty: null  }),  methods: {    mySharedMethod () { ... },    myLocalMethod () { ... }  }}
复制代码


Mixins 被认为“有害”

早在 2016 年年中,丹·阿布拉莫夫(Dan Abramov)撰写了《被认为有害的 Mixins》,他在文章中辩称,使用 mixins 在 React 组件中重用逻辑是一种反模式,主张改为远离它们。

不幸的是,他提到的关于 React 混合的缺点同样适用于 Vue。在了解 Composition API 如何克服这些缺点之前,让我们熟悉这些缺点。

命名冲突

我们看到了混合模式如何在运行时合并两个对象。如果他们都共享同名,会发生什么?


const mixin = {  data: () => ({    myProp: null  })}

export default { mixins: [mixin], data: () => ({ // same name! myProp: null })}
复制代码


这是合并策略的地方起作用的地方。这是一组规则,用于确定组件包含多个具有相同名称的选项时会发生什么。

Vue 组件的默认(但可以配置)合并策略指示本地选项将覆盖混合选项。虽然有例外。例如,如果我们有多个相同类型的生命周期挂钩,则将它们添加到挂钩数组中,并将依次调用所有挂钩。

即使我们不应该遇到任何实际的错误,但是在跨多个组件和 Mixins 的命名属性进行处理时,编写代码也变得越来越困难。一旦将第三方混合作为具有自己的命名属性的 npm 软件包添加到 npm 包中,可能会引起冲突,这尤其困难。

隐式依赖

混合和使用它的组件之间没有层次关系。这意味着组件可以使用在 mixin 中定义的数据属性(例如 mySharedDataProperty),但是 mixin 也可以使用假定在组件中定义的数据属性(例如 myLocalDataProperty)。当使用混入来共享输入验证时,通常是这种情况。mixin 可能期望组件具有一个输入值,该值将在其自己的 validate 方法中使用。

但是,这可能会导致问题。如果我们以后要重构组件并更改 mixin 所需的变量的名称,会发生什么?在查看组件时,我们不会发现任何错误。皮棉绒也不会捡起来。我们只会在运行时看到错误。

现在想象一下一个带有一堆 mixin 的组件。我们可以重构本地数据属性,还是会破坏混合?哪个混蛋?我们必须手动搜索它们才能知道。

从 mixins 迁移

Dan 的文章提供了 mixin 的替代方法,包括高阶组件,实用程序方法和其他一些组件组成模式。

尽管 Vue 在许多方面与 React 相似,但他建议的替代模式并不能很好地转化为 Vue。因此,尽管这篇文章是在 2016 年中撰写的,但从那时起,Vue 开发人员就一直遇到混合问题。

到现在。mixins 的缺点是 Composition API 背后的主要推动因素之一。在查看它如何克服 mixin 问题之前,让我们快速概述一下它的工作原理。

撰写 API 速成课程

Composition API 的关键思想是,与其将组件的功能(例如状态,方法,计算属性等)定义为对象属性,不如将它们定义为从新 setup 函数。

以定义了“计数器”功能的 Vue 2 组件的经典示例为例:


//Counter.vueexport default {  data: () => ({    count: 0  }),  methods: {    increment() {      this.count++;    }  },  computed: {    double () {      return this.count * 2;    }  }}
复制代码


接下来是使用 Composition API 定义的完全相同的组件。


// Counter.vueimport { ref, computed } from "vue";

export default { setup() { const count = ref(0); const double = computed(() => count * 2) function increment() { count.value++; } return { count, double, increment } }}
复制代码


您首先会注意到我们导入了一个 ref 函数,该函数允许我们定义一个反应变量,其功能与 data 变量。计算函数的情况与此相同。

该 increment 方法不是被动的,因此可以将其声明为纯 JavaScript 函数。注意,我们需要更改子属性 value 才能更改 count 反应变量的值。那是因为使用 ref 必须是对象,以便在传递时保持其反应性。

最好查阅 Vue Composition API 文档,以详细了解 ref 的工作原理。

一旦定义了这些功能,就可以从设置函数中返回它们。上面两个组件之间的功能没有区别。我们所做的只是使用替代 API。

提示: Composition API 将是 Vue 3 的核心功能,但您也可以在 Nue 插件中的 NPM 插件中使用它 @vue/composition-api。

代码提取

Composition API 的第一个明显优点是提取逻辑很容易。

让我们使用 Composition API 重构上面定义的组件,以使我们定义的功能位于 JavaScript 模块中 useCounter。(在功能描述前加“ use”是 Composition API 的命名约定。)


// useCounter.jsimport { ref, computed } from "vue";

export default function () { const count = ref(0); const double = computed(() => count * 2) function increment() { count.value++; } return { count, double, increment }}
复制代码


代码重用

要在组件中使用该功能,我们只需将模块导入到组件文件中并调用它(注意导入是一个函数)。这将返回我们定义的变量,随后我们可以从设置函数中返回它们。


// MyComponent.jsimport useCounter from "./useCounter.js";
export default { setup() { const { count, double, increment } = useCounter(); return { count, double, increment } }}
复制代码


乍一看,这看起来似乎有些冗长且毫无意义,但让我们看看这种模式如何克服了前面讨论的 mixins 问题。

命名冲突...解决了!

我们之前已经了解了 mixin 如何使用与消费组件中的名称同名的属性,或者甚至更阴险地使用消费组件使用的其他 mixin 中的属性。

组成 API 并不是问题,因为我们需要显式命名组成函数返回的任何状态或方法:


export default { setup () { const { someVar1, someMethod1 } = useCompFunction1(); const { someVar2, someMethod2 } = useCompFunction2(); return { someVar1, someMethod1, someVar2, someMethod2 } }}
复制代码


命名冲突将以与其他 JavaScript 变量相同的方式解决。

隐式依赖...解决了!

我们之前还看到了 mixin 如何使用消费组件上定义的数据属性,这可能会使代码易碎且难以推理。

合成函数还可以调用在使用组件中定义的局部变量。但是,不同之处在于,现在必须将此变量显式传递给 composition 函数。


import useCompFunction from "./useCompFunction";

export default { setup () { // some local value the a composition function needs to use const myLocalVal = ref(0);

// it must be explicitly passed as an argument const { ... } = useCompFunction(myLocalVal); }}
复制代码


包起来

mixin 模式在表面上看起来非常安全。但是,通过合并对象共享代码成为一种反模式,这是因为它增加了代码的脆弱性,并且掩盖了对功能进行推理的能力。

Composition API 最聪明的部分是,它允许 Vue 依靠本机 JavaScript 内置的安全措施来共享代码,例如将变量传递给函数和模块系统。

这是否意味着 Composition API 在各个方面都优于 Vue 的经典 API?不会。在大多数情况下,您可以坚持使用经典 API。但是,如果您打算重用代码,那么 Composition API 无疑是上乘的。


发布于: 2020 年 07 月 08 日阅读数: 289
用户头像

志学Python

关注

Ken 2019.06.12 加入

不断的探索尝试,不断探索尝试,不断探索尝试,永远不要放弃学习,前进,追求卓越,幸福就会追着你跑了,去发现自己的闪光点,在追求幸福的道路上,难免坎坷,但是思维决定幸福层度 在这里不仅仅只有技术

评论

发布
暂无评论
Vue3 Composition API如何替换Vue Mixins