【Vue】【选项式API】组合选项 – provide、inject、mixins、extends

前言

provide/inject、mixins是我们开发过程中经常会使用到的API,这几个API的相关了解大家知道多少呢?且听我们缓缓道来

一、provide/inject

provide 和 inject 通常成对一起使用,使一个祖先组件作为其后代组件的依赖注入方,无论这个组件的层级有多深都可以注入成功,只要他们处于同一条组件链上。

1.1 provide(提供)/ inject(注入)介绍

  • provide:用于提供可以被后代组件注入的值。
  • inject:用于声明要通过从上层提供方匹配并注入当前组件的属性

1.2 provide(提供)/ inject(注入)使用

1.2.1 provide(提供)

provide选项应当是一个对象或是返回一个对象的函数。这个对象包含了可注入其后代组件的属性,你可以在这个对象中使用 Symbol 类型的值作为 key

1.2.2 inject(注入)

inject 选项应该是以下两种之一:

  • 一个字符串数组

    export default {
      inject: ['foo'],
      created() {
        console.log(this.foo)
      }
    }
    
  • 一个对象,其 key 名就是在当前组件中的本地绑定名称,而它的值是以下两种之一:

    • 匹配可用注入的key(string 或 Symbol)
    • 一个对象
      • 它的 from 属性是一个key(String 或 Symbol),用于匹配可用的注入
      • 它的 default 属性用作候补值,和props 的默认值类似,如果它是一个对象,那么应该使用一个工厂函数来创建,以避免多个组件共享同一个对象

注入属性的值 = 匹配的属性 ? 匹配的属性值 : (默认值 || undefind)

1.2.3 Vue2 的 provide(提供)/ inject(注入)使用

provide / inject 类似于消息的订阅和发布。provide 提供或发送数据, inject 接收数据。

//父组件
export default{
    provide:{
        info:"提供数据",
    }
}


//子组件
export default{
    inject:['info'],
    mounted(){
        console.log("接收数据:", this.info) // 接收数据:提供数据
    }
} 

1.2.4 Vue3 的 provide(提供)/ inject(注入)使用

在组合式API中使用 provide/inject ,两个只能在 setup 期间调用,使用之前,必须从 Vue 显示导入 provide/inject 方法

参数:

  • provide 函数接收两个参数:provide( name,value )
    • name: 定义提供 property 的 name
    • value: property 的值
  • inject 函数有两个参数:inject(name,default)
    • name: 接收 provide 提供的属性名
    • default:设置默认值,可以不写,是可选参数
//父组件代码
<script>
import { provide } from "vue"
export default {
    setup(){
      provide('info',"值")
    }
}
</script>

//子组件 代码
<template>
  {{info}}
</template>
<script>
import { inject } from "vue"
export default {
    setup(){
      const info = inject('info')
      return{
        info
      }
    }
}
</script>

1.3 provide 和 inject 的优缺点

  • 优点:
    • 解决多嵌套组件时,运用prop层层传递的问题
  • 缺点:
    • 无法追踪数据的来源:在任意层级都能访问导致数据追踪比较困难,不知道是哪一层声明了这个,不知道哪一个层级或若干个层级使用了
    • 导致组件间的耦合:它将导致于组件间的耦合,使得组件复用性收到影响

1.4 其它

1. provide 和 inject 出现的背景

多层级的嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

【Vue】【选项式API】组合选项 - provide、inject、mixins、extends

注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

provide 和 inject 可以帮助我们解决这一问题。  一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

【Vue】【选项式API】组合选项 - provide、inject、mixins、extends

2. provide 和 inject 为什么不是响应式

  • 官方解释:当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。
  • 个人理解:会增加组件的复杂度,使得组件维护成本增加

二、mixins

2.1 mixins介绍

一个包含组件选项对象的数组,这些选项都将被混入到当前组件的实例中。

mixins选项接受一个 mixin 对象数组,这些 mixin 对象可以像普通的实例对象一样包含实例选项,它们将使用一定的选项合并逻辑与最终的选项进行合并。

举例来说,如果你的 mixin 包含一个created钩子,而组件自身也有一个,那么这两个函数都会被调用

  • mixins本质:其实就是一个JS对象,它可以包含我们组件中任意功能选项,如datacomponentsmethodscreatedcomputed等等

  • mixins作用:将相同的逻辑和功能抽离出来,分成单个文件,组件只需引入 mixins 就可以实现相同功能

在Vue2中,mixins 是创建可重复组件逻辑的主要方式。尽管在Vue3中保留了 mixins 支持,但对于组件间的逻辑复用,使用组合式 API 的组合式函数是现在更推荐的方式。

2.2 mixins使用

2.2.1 局部混入

使用大致步骤如下流程:

  1. 在src文件夹中创建mixins文件夹,在里面去写对应的mixin.js文件。如下所示:

    var myMixin = {
      created: function () {
        this.hello()
      },
      methods: {
        hello: function () {
          console.log('hello from mixin!')
        }
      }
    }
    
  2. 在组件中引入mixin,去使用如下所示:

    Vue.component('componentA',{
      mixins: [myMixin]
    })
    

该组件在使用的时候,混合了mixin里面的方法,在自动执行created生命钩子,执行hello方法

2.2.2 全局混入

通过Vue.mixin()进行全局的混入,如下所示:

Vue.mixin({
  created: function () {
      console.log("全局混入")
    }
})

使用全局混入需要特别注意,因为它会影响到每一个组件(包括第三方组件)

  • 使用场景:插件的编写

2.3 mixins特性

  1. mixins中的生命周期会与引入mixins的组件的生命周期整合在一起调用,而且mixins中的生命周期函数会比引入mixins的组件调用的快

    如果相同选项为生命周期钩子的时候,会合并成一个数组,先执行mixin的钩子,再执行组件的钩子

  2. 组件的datamethodsfilters会覆盖mixins里的同名datamethodsfilters

  3. 不同mixin里的同名方法,会按照引进的顺序,最后的覆盖前面的同名方法

2.4 mixins的优缺点

  • 优点:
    1. 提高代码复用性
    2. 无需传递状态
    3. 维护方便,只需要修改一个地方即可
  • 缺点:
    1. 变量来源不明确(隐式引入),不利于阅读,使得代码变得难以维护

      • 组件中引入mixin,并且直接隐式调用 mixin 里的变量/方法,这会让我们有时候找不到这个变量/方法的出处
      • 同一个组件可以引入多个mixin,并且直接调用mixin里的变量/方法,这会让我们有时候混乱 区分不出这些变量和方法 分别是哪个mixin里的?
    2. 多个mixins的生命周期会融合到一起运行,但是同名属性、方法无法融合,可能会导致冲突或覆盖

      比如组件1中的方法要输入属性info,但是组件2中也有同名属性info,且覆盖了组件1中的属性info,那么当执行组件1中的方法时,输出的确实组件2中的书写。这个我们可以避免,但是一不小心就会导致冲突,很容易制造混乱

    3. mixins和组件可能出现多对多的关系,复杂度较高

      即一个组件可以引用多个mixins,一个mixins也可以被多个组件引用

2.5 其它

1. mixins 与 vuex的区别

vuex:用来做状态管理的,里面定义的变量在每个组件中均可以使用和修改,在任意组件中修改次变量的值后,其他组件中此变量的值也会随之修改

Mixins:可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值在修改在组件中不会相互影响

2. mixins 与 公共组件的区别

组件:在父组件中引入组件,相当于在父组件中给出一个独立的空间供子组件使用,然后根据props进行父到子组件的传值,但本质上两者是相对独立的

Mixins:则是在引入组件之后与组件中的对象和方法进行合并,相当于扩展了父组件的对象与方法,可以理解为形成一个新的组件

三、extends

3.1 extends介绍

extends 要继承的“基类”组件。就是一个组件可以继承另一个组件的组件选项

!!!不建议用于组合式 API

extends 是为选项式 API 设计的,不会处理 setup() 钩子的合并。

在组合式 API 中,逻辑复用的首选模式是“组合”而不是“继承”。如果一个组件中的逻辑需要复用,考虑将相关逻辑提取到组合式函数中。

如果你仍然想要通过组合式 API 来“继承”一个组件,可以在继承组件的 setup() 中调用基类组件的 setup()

import Base from './Base.js'
export default {
  extends: Base,
  setup(props, ctx) {
    return {
     ...Base.setup(props, ctx),
      // 本地绑定
    }
  }
}

3.2 extends使用

const CompA = { ... }

const CompB = {
  extends: CompA,
  ...
}

3.3 其它

1. extends 与 mixins 的区别

从显示角度来看,extends 几乎和 mixins 相同。通过 extends 指定的组件将会当做第一个mixin来处理。

然而,extends 和 mixins 表达的是不同的目标。mixins 选项基本用于组合功能,extends 则一般更关注继承关系

资料来源

原文链接:https://juejin.cn/post/7319330542100250636 作者:旺仔小猪

(0)
上一篇 2024年1月2日 下午4:22
下一篇 2024年1月3日 上午10:05

相关推荐

发表回复

登录后才能评论