由于内容较多,我将其分为了里两部分:
Vue3较Vue2的更新内容(二)>>>
v2:
<div ref="xxx">my refdiv>
this.$refs.xxx//获取ref绑定元素
v3:
<div :ref="xxx">my refdiv>
export default {
methods: {
xxx(el){
console.log(el);//获取绑定元素
//this.myRef = el;//(保存获取到的元素)
}
}
}
2、新增 异步组件
v2:
在v2是通过返回Promise函数来创建的
const Component1 = () => import('./Component1.vue')//v2 异步组件
//或者,对于带有选项的更高阶的组件语法:
const Component2 = {//v2 异步组件
component: () => import('./Component2.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
}
v3
v3新增了defineAsyncComponent 方法来定义异步组件
import {defineAsyncComponent} from 'vue'
// 无选项异步组件
const Component1 = defineAsyncComponent(() => import('./Component1.vue'))
// 带选项异步组件
const Component2 = defineAsyncComponent({
loader: () => import('./Component2.vue'),
delay: 200,
timeout: 3000,
errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
3、Vue3中$attrs包含class & style
给组件添加属性
<TestAttrs id="my-id" class="my-class">TestAttrs>
TestAttrs.vue:
<template>
<label>
<input type="text" v-bind="$attrs" />
<!--VUE2 class .my-class不生效 -->
<!--VUE3 class .my-class生效 -->
</label>
</template>
<script>
export default {
inheritAttrs: false,
created() {
console.log(this.$attrs);
//VUE2: {id: "my-id"}
//VUE3: {class: "my-class",id: "my-id"}
}
}
</script>
<style scoped="scoped">
input.my-class {
background: red;
}
</style>
v2生成html:
<label class="my-class">
<input type="text" id="my-id" />
label>
input.my-class 的 样式没生效
this.$attrs:{id: “my-id”}
v3生成html:
<label>
<input type="text" id="my-id" class="my-class" />
label>
input.my-class 的 样式生效
this.$attrs:{class: “my-class”,id: “my-id”}
在Vue2,可以使用 this.$children 访问当前实例的直接子组件。
但在Vue3, $children property 已被移除,且不再支持。如果你需要访问子组件实例,我们建议使用 $refs。
<p v-highlight="'yellow'">以亮黄色高亮显示此文本p>
v2:
// v2 自定义指令
Vue.directive('highlight', {
bind(el, binding, vnode) {
el.style.background = binding.value
const vm = vnode.context//获取vue实例
}
})
钩子(可选):
bind - 指令绑定到元素后调用。只调用一次。
inserted - 元素插入父 DOM 后调用。
update - 当元素更新,但子元素尚未更新时,将调用此钩子。
componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。
unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次。
v3:
const app = Vue.createApp({})
// v3 自定义指令
app.directive('highlight', {
beforeMount(el, binding, vnode) {
el.style.background = binding.value
const vm = binding.instance //获取vue实例
}
})
钩子(可选):
created - 新增!在元素的 attribute 或事件监听器被应用之前调用。
bind → beforeMount
inserted → mounted
beforeUpdate:新增!在元素本身被更新之前调用,与组件的生命周期钩子十分相似。
update → 移除!该钩子与 updated 有太多相似之处,因此它是多余的。请改用 updated。
componentUpdated → updated
beforeUnmount:新增!与组件的生命周期钩子类似,它将在元素被卸载之前调用。
unbind -> unmounted
*需要注意的是 v2通过 vnode.context 获取实例对象,现在v3 通过binding.instance 获取
6、使用自定义元素自定义元素
<plastic-button>plastic-button>
v2语法:
Vue.config.ignoredElements = ['plastic-button']
v3语法:
如果使用动态模板编译,使用app.config.compilerOptions.isCustomElement
const app = Vue.createApp({})
app.config.compilerOptions.isCustomElement = tag => tag === 'plastic-button'
可能会有 warn 警告
如果使用了 vue-loader,则通过 vue-loader 的 compilerOptions 选项传递
// webpack 中的配置
rules: [
{
test: /\.vue$/,
use: 'vue-loader',
options: {
compilerOptions: {
isCustomElement: tag => tag === 'plastic-button'
}
}
}
// ...
]
*需要注意的是,运行时配置只会影响运行时的模板编译——它不会影响预编译的模板。
7、data选项 用法在 v2 中,开发者可以通过 object 或者是 function 定义 data 选项。
data: {
apiKey: 'a1b2c3'
}
在 v3 中,data 选项已标准化为只接受返回 object 的 function。
data() {
return {
apiKey: 'a1b2c3'
}
}
8、Mixin 合并行为变更
在v3,当来自组件的 data() 及其 mixin 或 extends 基类被合并时,合并 *** 作现在将被浅层次地执行
合并示例:
const Mixin = {
data() {
return {
user: {
name: 'Jack',
id: 1
}
}
}
}
const CompA = {
mixins: [Mixin],
data() {
return {
user: {
id: 2
}
}
}
}
v2 生成的 $data:
{
"user": {
"id": 2,
"name": "Jack"
}
}
9、新增emits选项
Vue 3 提供一个 emits 选项,和现有的 props 选项类似。这个选项可以用来定义一个组件可以向其父组件触发的事件。
<template>
<div>
<p>{{ text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text'],
emits: ['accepted']
}
</script>
emits内定义可向其父组件触发的事件,即 $emit()的第一个参数
该选项也可以接收一个对象,该对象允许开发者定义传入事件参数的验证器,和 props 定义里的验证器类似。
尝试后发现,当向其父组件触发的事件未在emits选项定义或未验证成功,控制台会出现warn警告,但父级仍然触发了该事件
Vue3中完全移除了 o n 、 on、 on、off 和 o n c e 方 法 , 组 件 实 例 不 再 实 现 事 件 触 发 接 口 。 once 方法,组件实例不再实现事件触发接口。 once方法,组件实例不再实现事件触发接口。emit 仍然包含于现有的 API 中,因为它用于触发由父组件声明式添加的事件处理函数。
11、移除 过滤器(filters)在 vue3 中,过滤器已移除,且不再支持。取而代之的是,用方法调用或计算属性来替换它们。
有点心痛呀,觉得 filters 还挺好用的
不少项目在处理时间格式的时候会选择全局过滤器处理格式,迁移的话也需一定的成本
Vue 3 现在正式支持了多根节点的组件,也就是片段!
在 v2 ,由于不支持多根节点组件,当其被开发者意外地创建时会出现报错。结果是,为了修复这个问题,许多组件被包裹在了一个
在 v3 中,组件可以包含多个根节点!但是,这要求开发者显式定义 attribute 应该分布在哪里。 13、函数式组件
在 v3 中,v2 带来的函数式组件的性能提升可以忽略不计,因此官方建议只使用有状态的组件
所以这部分内容可以只了解了解
vue 2 使用函数式组件
export default {
functional: true,
props: ['level'],
render(h, { props, data, children }) {
return h(`h${props.level}`, data, children)
}
}
vue 3 使用函数式组件
在 v3 中,所有的函数式组件都是用普通函数创建的。换句话说,不需要定义 { functional: true } 组件选项。如果是单文件组件中使用 创建函数式组件的话,functional属性也已被移除。
它们将接收两个参数:props 和 context。context 参数是一个对象,包含组件的 attrs、slots 和 emit property。
此外,h 现在是全局导入的,而不是在 render 函数中隐式提供。
import { h } from 'vue'
const DynamicHeading = (props, context) => {
return h(`h${props.level}`, context.attrs, context.slots)
}
DynamicHeading.props = ['level']
export default DynamicHeading
14、全局 API
在vue2,全局配置使得在同一页面上的多个“应用”在全局配置不同时共享同一个 Vue 副本非常困难,使用Vue.mixin会影响到所有根实例,为了避免这些问题,在 Vue 3 中引入了一个新的全局 API:createApp
调用 createApp 创建一个应用实例:
import {
createApp
} from 'vue'
import App from './App.vue'
const app = createApp(App)
挂载:
app.mount('#app')
任何全局改变 Vue 行为的 API 现在都会移动到应用实例上,下面选自官方的内容图片:
由于之前的 Vue 版本中的代码编写方式,如 Vue.nextTick() 这样的全局 API 是不支持 tree-shake 的,不管它们实际上是否被使用了,都会被包含在最终的打包产物中。在 Vue 3 中,全局和内部 API 都经过了重构,并考虑到了 tree-shaking 的支持。因此,对于 ES 模块构建版本来说,全局 API 现在通过具名导出进行访问。
以 全局 API Vue.nextTick() 为例:
v2:
import Vue from 'vue'
Vue.nextTick(() => {
// 一些和 DOM 有关的东西
})
v3:
import { nextTick } from 'vue'
nextTick(() => {
// 一些和 DOM 有关的东西
})
16、内联模板 Attribute
在 v2 中,Vue 为子组件提供了 inline-template attribute,以便将其内部内容作为模板使用,而不是作为分发内容。
<my-component inline-template>
<div>
<p>它们将被编译为组件自己的模板,</p>
<p>而不是父级所包含的内容。</p>
</div>
</my-component>
而现在v3将不再支持此功能。
17、key Attribute 改动对于 v-if/v-else/v-else-if 的各分支项 key 将不再是必须的,因为现在 Vue 会自动生成唯一的 key。
如果你手动提供 key,那么每个分支必须使用唯一的 key。你将不再能通过故意使用相同的 key 来强制重用分支。
v2 v-if/v-else/v-else-if 使用key:
<!-- Vue 2.x -->
<div v-if="condition" key="yes">Yes</div>
<div v-else key="no">No</div>
这个示例在 Vue 3.x 中仍能正常工作。但是我们不再建议在 v-if/v-else/v-else-if 的分支中继续使用 key attribute,因为没有为条件分支提供 key 时,也会自动生成唯一的 key。
<!-- Vue 3.x -->
<div v-if="condition">Yes</div>
<div v-else>No</div>
结合 template v-for
在 Vue 2.x 中, 标签不能拥有 key。不过,你可以为其每个子节点分别设置 key。
<!-- Vue 2.x -->
<template v-for="item in list">
<div :key="'heading-' + item.id">...</div>
<span :key="'content-' + item.id">...</span>
</template>
在 Vue 3.x 中,key 则应该被设置在 标签上。
<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>
类似地,当使用 时如果存在使用 v-if 的子节点,则 key 应改为设置在 标签上。
下一章:Vue3较Vue2的更新内容(二)>>>
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)