从vue2迁移到vue3,细节处有啥变化?
一、说明
其实vue3大部分的知识点和vue2都是一样的,这篇文章是介绍vue2中部分属性在vue3中的变化,以及vue3新增加的一些比较重要的 东西。 |
---|
二、子传父时使用的emit
- 在 Vue 2 中,你可以定义一个组件可接收的 prop,但是你无法声明它可以触发哪些事件
<template>
<div>
<p>{
{
text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text']
}
</script>
- 在vue3中,和 prop 类似,现在可以通过 emits 选项来定义组件可触发的事件
<template>
<div>
<p>{
{
text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text'],
emits: ['accepted']
}
</script>
该选项也可以接收一个对象,该对象允许开发者定义传入事件参数的验证器,和 props 定义里的验证器类似
举个例子
我们封装一个CounterOperation.vue的组件
内部其实是监听两个按钮的点击,点击之后通过 this.$emit的方式发出去事件
- 自定义事件的时候,我们也可以传递一些参数给父组件
- 在vue3当中,我们可以对传递的参数进行验证
三、$children
在 2.x 中,开发者可以使用 this.$children 访问当前实例的直接子组件:
<template>
<div>
<img alt="Vue logo" src="./assets/logo.png">
<my-button>Change logo</my-button>
</div>
</template>
<script>
import MyButton from './MyButton'
export default {
components: {
MyButton
},
mounted() {
console.log(this.$children) // [VueComponent]
}
}
</script>
在Vue3中已经移除了$children的属性,所以不可以使用了。如果你需要访问子组件实例,我们建议使用 $refs |
---|
四、异步组件
-
新的
defineAsyncComponent
助手方法,用于显式地定义异步组件 -
component 选项被重命名为 loader
-
Loader 函数本身不再接收 resolve 和 reject 参数,且必须返回一个 Promise
在vue2.x中 -
异步组件是通过将组件定义为返回 Promise 的函数来创建的,例如:
const asyncModal = () => import('./Modal.vue')
- 或者,对于带有选项的更高阶的组件语法
const asyncModal = {
component: () => import('./Modal.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
}
在 Vue 3 中
- 由于函数式组件被定义为纯函数,因此异步组件需要通过将其包裹在新的
defineAsyncComponent
助手方法中来显式地定义
import {
defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'
// 不带选项的异步组件
const asyncModal = defineAsyncComponent(() => import('./Modal.vue'))
// 带选项的异步组件
const asyncModalWithOptions = defineAsyncComponent({
loader: () => import('./Modal.vue'),
delay: 200,
timeout: 3000,
errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
与 2.x 不同,loader 函数不再接收 resolve 和 reject 参数,且必须始终返回 Promise。
// 2.x 版本
const oldAsyncComponent = (resolve, reject) => {
/* ... */
}
// 3.x 版本
const asyncComponent = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
/* ... */
})
)
五、$attrs包含class&style
$attrs 现在包含了所有传递给组件的 attribute,包括 class 和 style |
---|
2.x 行为
- Vue 2 的虚拟 DOM 实现对 class 和 style attribute 有一些特殊处理。因此,与其它所有 attribute 不一样,它们没有被包含在 $attrs 中。
- 上述行为在使用 inheritAttrs: false 时会产生副作用
- $attrs 中的 attribute 将不再被自动添加到根元素中,而是由开发者决定在哪添加
- 但是 class 和 style 不属于 $attrs,它们仍然会被应用到组件的根元素中
<template>
<label>
<input type="text" v-bind="$attrs" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
像这样使用时:
<my-component id="my-id" class="my-class"></my-component>
将生成以下 HTML:
<label class="my-class">
<input type="text" id="my-id" />
</label>
3.x 行为
$attrs 包含了所有的 attribute,这使得把它们全部应用到另一个元素上变得更加容易了。现在上面的示例将生成以下 HTML
<label>
<input type="text" id="my-id" class="my-class" />
</label>
六、自定义指令
2.x 语法
- 在 Vue 2 中,自定义指令通过使用下列钩子来创建,以对齐元素的生命周期,它们都是可选的
- bind - 指令绑定到元素后调用。只调用一次
- inserted - 元素插入父 DOM 后调用。
- update - 当元素更新,但子元素尚未更新时,将调用此钩子
- componentUpdated - 一旦组件和子级被更新,就会调用这个钩子
- unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次
下面是一个例子:
<p v-highlight