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), // 本地绑定 } } }