vue3 新功能
Provide / Inject
通常,当我们需要从父组件向子组件传递数据时,我们使用 props。但一些深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
对于这种情况,我们可以使用一对 provide 和 inject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据。
–
实际上,你可以将依赖注入看作是“长距离的 prop”,除了:
- 父组件不需要知道哪些子组件使用了它 provide 的 property
- 子组件不需要知道 inject 的 property 来自哪里
1 |
|
但默认情况下,provide/inject 绑定并不是响应式的,可以为 provide 分配一个组合式 API computed property:
1 |
|
生命周期钩子
下表包含如何在 setup () 内部调用生命周期钩子:
选项式 API | Hook inside setup |
---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。
组合式 API
使用
(data、computed、methods、watch)
组件选项时,当我们的组件开始变得很大时,逻辑关注点也会增长,并且组件会难以阅读和理解。组合式 API 意在把同一个逻辑关注点相关代码收集在一起抽成单个可复用的模块。
为了开始使用组合式 API,我们首先需要一个可以实际使用它的地方。在 Vue 组件中,我们将此位置称为<font style="color:rgb(44, 62, 80);"></font><font style="color:rgb(71, 101, 130);">setup</font>
。
新的 setup 选项在组件被创建之前执行,一旦 props 被解析完成,它就将被作为组合式 API 的入口。
setup** 选项是一个接收 **props** 和 **context** 的函数,我们将在之后进行讨论。此外,我们将 **setup** 返回的所有内容都暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。**
1 |
|
Context
传递给 setup 函数的第二个参数是 context。context 是一个普通 JavaScript 对象,暴露了其它可能在 setup 中有用的值:
1 |
|
context 是一个普通的 JavaScript 对象,也就是说,它不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构。
1 |
|
attrs 和 slots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.x 或 slots.x 的方式引用 property。请注意,与 props 不同,attrs 和 slots 的 property 是非响应式的。如果你打算根据 attrs 或 slots 的更改应用副作用,那么应该在 onBeforeUpdate 生命周期钩子中执行此操作。
注意事项
- setup 参数里的 props 是响应式的,但你不能使用 ES6 解构,它会消除 prop 的响应性。如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成此操作
1 |
|
执行 setup 时,你只能访问以下 property:props,attrs,slots,emit;换句话说,你将无法访问以下组件选项:data (
<font style="color:rgb(44, 62, 80);">可用 ref | reactive 代替</font>
) 、computed (<font style="color:rgb(44, 62, 80);">组合api代替</font>
)、methods (<font style="color:rgb(44, 62, 80);">setup中的方法就是 methods</font>
)、模板的 refs (<font style="color:rgb(44, 62, 80);">同react-useRef,ref绑定在模板上即可获取组件实例</font>
)refs 在 vue 的 template 模板中,会自动解包,就是不需要使用
<font style="color:rgb(44, 62, 80);">.value</font>
就可获取其值,但是使用 jsx 语法时 必须 使用<font style="color:rgb(44, 62, 80);">.value</font>
才能拿到值
- 都用 setup 了,就不需要使用 this 了,使用 this 容易与其它选项式 API 产生混淆
粗略认识
- toRef, 可以用于定义可选 props, toRefs 多用于解构 props
1 |
|
ref 与 reactive 的区别
reactive() 用于创建引用类型响应数据
ref() 用于创建基本类型响应数据,但他也可以创建引用类型的响应数据,但是 ref 本质上 最后还是会调用 <font style="color:rgb(64, 64, 64);">reactive</font>
,
ref 返回的是 RefImpl,而 ref 的 RefImpl._value(可以通过控制台打印查看到 RefImpl 内的_value)是一个 reactive 代理的原始对象;reactive 返回就是一个 Proxy 了。
要使用这个语法,需要将 setup attribute 添加到 代码块上:
1 |
|
里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 只在组件被首次引入的时候执行一次不同, 中的代码会在每次组件实例被创建的时候执行。
- 顶级绑定都会暴露给模板,也就是
<script setup>
声明了的变量还是函数,在模板中都可以直接使用 - 无论是
import
组件还是import
方法,无须另外绑定,只要import
了,模板中就可直接使用 - 使用 vNameOfDirective 的格式来命名本地自定义指令,可以使得它们可以直接在模板中使用。
1 |
|
- 在