vuejs3.0 从入门到精通——provide、inject、mixins、extends

provide、inject、mixins、extends

一、provide

  用于提供可以被后代组件注入的值。

interface ComponentOptions {
  provide?: object | ((this: ComponentPublicInstance) => object)
}
    • interface ComponentOptions:定义了一个名为 ComponentOptions 的接口。在 Vue.js 中,组件选项是一个对象,用于定义组件的行为、属性等。
    • provide?:provide 是 ComponentOptions 接口中的一个可选属性。provide 属性用于在组件的子孙组件中注入依赖,是 Vue 的依赖注入机制的一部分。
    • object | ((this: ComponentPublicInstance) => object):这是 provide 属性的类型定义,表示 provide 可以是一个对象,或者是一个返回对象的函数。
      • object:表示 provide 可以是一个对象,该对象包含可注入的属性。
      • ((this: ComponentPublicInstance) => object):表示 provide 也可以是一个函数,该函数返回一个对象。函数的 this 上下文被类型化为 ComponentPublicInstance,这是 Vue 组件实例的公共部分。这样的类型注解确保了函数内部的 this 上下文具有 ComponentPublicInstance 类型,从而可以使用该类型的属性和方法。
    • provide和inject通常成对一起使用,使一个祖先组件作为其后代组件的依赖注入方,无论这个组件的层级有多深都可以注入成功,只要他们处于同一条组件链上。
    • 这个provide选项应当是一个对象或是返回一个对象的函数。这个对象包含了可注入其后代组件的属性。你可以在这个对象中使用Symbol类型的值作为key。

示例:

基本使用方式:

const s = Symbol()

export default {
  provide: {
    foo: 'foo',
    [s]: 'bar'
  }
}
        • const s = Symbol(): 这里创建了一个唯一的 Symbol 类型的变量 s。Symbol 是 JavaScript 中的一种数据类型,每个 Symbol 值都是唯一的。这意味着即使你创建了多个 Symbol,它们也不会相等。
        • export default {...}: 这部分代码导出一个对象,这个对象将被用作 Vue 组件的选项。
        • provide: {...}: provide 是 Vue 组件的一个选项,它允许你向下传递数据,使得后代组件可以通过 inject 选项获取这些数据。
        • foo: 'foo': 在 provide 对象中,foo 是一个键,其对应的值是一个字符串 'foo'。这意味着,任何后代组件都可以通过 inject 选项获取到 'foo' 这个值,使用的键是 'foo'。
        • [s]: 'bar': 这里使用了计算属性名称(Computed Property Names)的特性,它允许你使用变量作为对象的键。在这里,变量 s(一个 Symbol)被用作键,字符串 'bar' 是对应的值。这意味着,后代组件可以通过 inject 选项和 Symbol s 来获取到 'bar' 这个值。
export default {
  data() {
    return {
      msg: 'foo'
    }
  }
  provide() {
    return {
      msg: this.msg
    }
  }
}
    • data 方法

data() 是一个方法,它返回一个对象。这个对象就是该 Vue 组件的局部状态(即数据)。
在返回的对象中,msg 是一个属性,其值为 'foo'。这意味着在该组件的模板和方法中,你可以通过 this.msg 来访问这个数据属性。

    • provide 方法

provide() 是另一个方法,它也返回一个对象。这个对象中的属性和值将被提供给该组件的后代组件。
在返回的对象中,msg 是一个属性,其值通过 this.msg 从组件的 data 中获取。这意味着后代组件可以通过 inject 选项来注入这个 msg,并访问其值 'foo'。

请注意,针对上面这个例子,所供给的msg将不会是响应式的。

二、inject

  用于声明要通过从上层提供方匹配并注入进当前组件的属性。

interface ComponentOptions {
  inject?: ArrayInjectOptions | ObjectInjectOptions
}

type ArrayInjectOptions = string[]

type ObjectInjectOptions = {
  [key: string | symbol]:
    | string
    | symbol
    | { from?: string | symbol; default?: any }
} 

  ComponentOptions 接口定义了一个可选的 inject 属性,其类型可以是 ArrayInjectOptions 或 ObjectInjectOptions。这使得开发者可以在使用 Vue 组件时更灵活地注入属性或者从父组件中获取属性。

  简要概述一下这两种类型:

    • ArrayInjectOptions:是一个字符串数组,数组中的每个字符串代表要从父组件中注入的属性名。
    • ObjectInjectOptions:是一个对象,该对象的每个键值对都表示一个要注入的属性。键是属性名,值可以是字符串、符号,或者一个具有 from 和 default 属性的对象。其中,from 属性表示从哪里注入属性,default 属性表示如果父组件没有提供该属性,那么将使用的默认值。

  请注意,注入绑定并非响应式的。这是有意为之的一个设计。如果要注入的值是一个响应式对象,那么这个对象上的属性将会保留响应性。请看配合响应性一节获取更多细节。

  示例:

基本使用方法:

export default {
  inject: ['foo'],
  created() {
    console.log(this.foo)
  }

使用注入的值作为 props 的默认值:

const Child = {
  inject: ['foo'],
  props: {
    bar: {
      default() {
        return this.foo
      }
    }
  }
} 

使用注入的值作为 data:

const Child = {
  inject: ['foo'],
  data() {
    return {
      bar: this.foo
    }
  }
}

注入项可以选择是否带有默认值:

const Child = {
  inject: {
    foo: { default: 'foo' }
  }
} 

如果需要从不同名字的属性中注入,请使用from指明来源属性。

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
}

和props默认值类似,对于非原始数据类型的值,你需要使用工厂函数:

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: () => [1, 2, 3]
    }
  }
}

 

三、mixins

https://cn.vuejs.org/api/options-composition.html#mixins

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

interface ComponentOptions {
  mixins?: ComponentOptions[]
}

  这是一个 TypeScript 的接口声明,名为 ComponentOptions。这个接口表示 Vue 组件的选项对象,用来定义 Vue 组件的配置和行为。

  在这个接口中,声明了一个名为 mixins 的属性,它的类型是 ComponentOptions[],也就是 ComponentOptions 的数组。mixins 属性是可选的,所以它的定义后面有一个 ? 符号。

在 Vue 2 中,mixins 是创建可重用组件逻辑的主要方式。尽管在 Vue 3 中保留了 mixins 支持,但对于组件间的逻辑复用,使用组合式 API 的组合式函数(https://cn.vuejs.org/guide/reusability/composables.html)是现在更推荐的方式。

示例:

const mixin = {
  created() {
    console.log(1)
  }
}

createApp({
  created() {
    console.log(2)
  },
  mixins: [mixin]
})

// => 1
// => 2

在这部分,我们使用createApp方法创建一个新的Vue应用。这个应用对象包含两个主要的部分:

    • 一个created生命周期钩子,当应用被创建时,它会打印数字2
    • mixins: [mixin]这部分代码表示我们要在这个应用中混入mixin对象。这意味着mixin中的所有内容(在这种情况下,是created钩子)将被添加到这个应用中,就好像它们直接在应用对象中定义一样。

  mixins选项接受一个 mixin对象数组。这些mixin对象可以像普通的实例对象一样包含实例选项,它们将使用一定的选项合并逻辑与最终的选项进行合并。举例来说,如果你的mixin包含了一个created钩子,而组件自身也有一个,那么这两个函数都会被调用。

  Mixin 钩子的调用顺序与提供它们的选项顺序相同,且会在组件自身的钩子前被调用。

四、extends

  要继承的“基类”组件。

interface ComponentOptions {
  extends?: ComponentOptions
}

使一个组件可以继承另一个组件的组件选项。

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

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

同mixins一样,所有选项(setup() 除外)都将使用相关的策略进行合并。

示例:

const CompA = { ... }

const CompB = {
  extends: CompA,
  ...
}
不建议用于组合式 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),
      // 本地绑定
    }
  }
}
posted @ 2023-11-13 11:03  左扬  阅读(226)  评论(0编辑  收藏  举报
levels of contents