想在你的Vue组件之间共享代码?如果你熟悉Vue 2 则可能知道使用mixin,但是新的Composition API 提供了更好的解决方案。

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

回顾Mixins功能

通常,Vue组件是由一个JavaScript对象定义的,它具有表示我们所需功能的各种属性,诸如data,methods,computed 等。

// MyComponent.js
export default {data: () => ({myDataProperty: null}),methods: {myMethod () { ... }}// ...
}

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

// MyMixin.js
export default {data: () => ({mySharedDataProperty: null}),methods: {mySharedMethod () { ... }}
}

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

// ConsumingComponent.js
import MyMixin from "./MyMixin.js";export default {mixins: [MyMixin],data: () => ({myLocalDataProperty: null}),methods: {myLocalMethod () { ... }}
}

对于这个特定的例子,在运行时使用的组件定义应该是这样的:

export default {data: () => ({mySharedDataProperty: nullmyLocalDataProperty: null}),methods: {mySharedMethod () { ... },myLocalMethod () { ... }}
}

Mixins被认为“有害”

早在2016年中期,丹·阿布拉莫夫(Dan Abramov)就写了《mixin被认为是有害的》(mixin Considered Harmful),他在书中辩称,将mixin用于在React组件中重用逻辑是一种反模式,主张远离它们。

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

命名冲突

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

const mixin = {data: () => ({myProp: null})
}export default {mixins: [mixin],data: () => ({// 同名!myProp: null})
}

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

Vue组件的默认(但可以配置)合并策略指示本地选项将覆盖mixin选项。Vue组件的默认(可选配置)合并策略指示本地选项将覆盖mixin选项。不过也有例外,例如,如果我们有多个相同类型的生命周期钩子,这些钩子将被添加到一个钩子数组中,并且所有的钩子都将被依次调用。

尽管我们不应该遇到任何实际的错误,但是在跨多个组件和mixin处理命名属性时,编写代码变得越来越困难。一旦第三方mixin作为带有自己命名属性的npm包被添加进来,就会特别困难,因为它们可能会导致冲突。

隐式依赖

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

不过,这可能会引起一些问题。如果我们以后想重构一个组件,改变了mixin需要的变量的名称,会发生什么情况呢?我们在看这个组件时,不会发现有什么问题。linter也不会发现它,我们只会在运行时看到错误。

现在想象一个有很多mixin的组件。我们可以重构本地数据属性吗?或者它会破坏mixin吗?我们得手动搜索才能知道。

从mixins迁移

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

mixins的缺点是Composition API背后的主要推动因素之一,让我们快速了解一下它是如何工作的,然后再看它如何克服mixin问题。

快速入门Composition API

Composition API的主要思想是,我们将它们定义为从新的 setup 函数返回的JavaScript变量,而不是将组件的功能(例如state、method、computed等)定义为对象属性。

以这个经典的Vue 2组件为例,它定义了一个“计数器”功能:

//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}}
}

首先会注意到,我们导入了 ref 函数,该函数允许我们定义一个响应式变量,其作用与 data 变量几乎相同。计算属性的情况与此相同。

increment 方法不是被动的,所以它可以被声明为一个普通的JavaScript函数。注意,我们需要更改子属性 count 的 value 才能更改响应式变量。这是因为使用 ref 创建的响应式变量必须是对象,以便在传递时保持其响应式。

定义完这些功能后,我们将从 setup 函数中将其返回。

代码提取

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

让我们使用Composition API重构上面定义的组件,以使我们定义的功能位于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}
}

代码重用

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

// MyComponent.js
import useCounter from "./useCounter.js";export default {setup() {const { count, double, increment } = useCounter();return {count,double,increment}}
}

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

命名冲突解决了

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

这不是Composition API的问题,因为我们需要显式命名任何状态或从合成函数返回的方法。

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

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

隐式依赖…解决了!

前面还看到mixin如何使用在消费组件上定义的 data 属性,这可能会使代码变得脆弱,并且很难进行推理。

合成函数(Composition Function)还可以调用消费组件中定义的局部变量。不过,不同之处在于,现在必须将此变量显式传递给合成函数。

import useCompFunction from "./useCompFunction";export default {setup () {// 某个局部值的合成函数需要用到const myLocalVal = ref(0);// 它必须作为参数显式地传递const { ... } = useCompFunction(myLocalVal);}
}

总结

mixin模式表面上看起来很安全。然而,通过合并对象来共享代码,由于它给代码增加了脆弱性,并且掩盖了推理功能的能力,因此成为一种反模式。

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

这是否意味着Composition API在各方面都比Vue的经典API优越?不是的。在大多数情况下,你坚持使用经典API是没有问题的。但是,如果你打算重用代码,Composition API无疑是优越的。

如若转载,请注明出处:开源字节   https://sourcebyte.cn/article/159.html

Vue3 Composition API如何替换Vue Mixins相关推荐

  1. Vue3 Composition API(一)——setup、reactive、ref、readonly

    一.Options API的弊端 在Vue2中,我们编写组件的方式是Options API: Options API的一大特点就是在对应的属性中编写对应的功能模块: 比如data定义数据.method ...

  2. Vue3 Composition API(三)——生命周期钩子、Provide函数 和 Inject函数、封装Hook案例、setup顶层编写方式

    一.生命周期钩子 我们前面说过 setup 可以用来替代 data . methods . computed .watch 等等这些选项,也可以替代 生命周期钩子. 那么setup中如何使用生命周期函 ...

  3. Vue3 Composition API(二)——computed、watchEffect、setup中使用ref

    一.computed 在前面我们讲解过计算属性computed:当我们的某些属性是依赖其他状态时,我们可以使用计算属性来处理 在前面的Options API中,我们是使用computed选项来完成的: ...

  4. vue3 Composition ApI总结

    1.setup setup中不能用this,因为setup是在实例被完全初始化之前的执行的,而在实例被初始化之前是没有this的, 它不能调用实例上的方法,但是实例上的方法可以调用它 2.响应式处理r ...

  5. js 表单设计器_准备迎接Vue3,使用Vue Composition API生成干净可扩展的表单

    表单是前端开发中最棘手的部分之一,您可能会在其中发现很多混乱的代码. Vue.js 2之类的基于组件的框架在提高前端代码的可伸缩性方面做了很多工作,但是形式问题仍然存在. 在本教程中,我将向您展示新的 ...

  6. Vue3.0 Composition API与Vue2.x 使用的 Options API

    Vue3.0 所采用的 Composition API 与 Vue2.x 使用的 Options API 有什么不同 开始之前 Composition API 可以说是Vue3最大的特点,那么为什么要 ...

  7. Vue3 -- 组合式API

    组合式API 组合式api(Composition API)算是vue3对我们开发者来说非常有价值的一个api更新,我们先不关注具体语法,先对它有一个大的感知 1. composition vs op ...

  8. 谈谈vue3组合式api的优势

    vue2: options API 配置式 使用传统Options API(配置式API)中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 . vue3: com ...

  9. vue3基础(一 )composition api,typeof,keyof,keyof typeof

    vue是渐进式框架 就是可以不全会,可以会一点用一点 vue3新特性: 破坏性变化: 迁移会出问题或者运行不了 移除: composition api 为vue应用提供更好的逻辑复用和代码组织 主要替 ...

最新文章

  1. 冲刺第九天 12.5 WED
  2. Ubuntu 使用root 帐号开启 SSH 登录
  3. 【离散数学中的数据结构与算法】十 汉诺塔
  4. 【Linux】Linux环境的搭建
  5. Pthon入门--range()函数
  6. 在线编辑器XhEditor
  7. 微信公众号推文封面图设置
  8. Eplan如何添加“连接定义点”
  9. python——获取矩形四个角点的坐标
  10. 项目延期,不重视过程项目团队将自食其果
  11. Spark Streaming读取Kafka数据的两种方式
  12. Python——解一元二次方程
  13. 区块链系列 - 以太坊简介
  14. 虚机安装Linux网络配置的一些笔记(隔离,桥接,NAT)
  15. 居家养老要智能化?阿里云构建民政大脑,引导民政进入智能化时代
  16. Hive中数据库和表的操作(HSQL)
  17. 计算机网络dce接口命令,思科路由器里查看此接口是DCE还是DTE端的命令是什么?...
  18. IDE工具(16) eclipse创建动态web工程搭建CMS开发环境(自动服务器tomcat)
  19. 游戏中的现代音频技术综述
  20. Qt最强软件例程1——qcanpool

热门文章

  1. 系统性能提升优先法宝 | 缓存应用实践
  2. Adaptec by PMC携业界首款配备加密技术的产品进军HBA市场
  3. 查准率与查全率的计算
  4. python社会网络分析教授_科学网—python 社会网络分析工具之networkx - 郗强的博文...
  5. 《奈飞文化手册》笔记
  6. 图像特征之颜色直方图
  7. linux下FTP服务启动与关闭命令(转)
  8. Http请求参数详解
  9. MurmurHash 哈希算法
  10. php图片本地化,PHP_php将远程图片保存到本地服务器的实现代码,php如何将远程图片本地化,本 - phpStudy...