由于内容较多,我将其分为了里两部分:
Vue3较Vue2的更新内容(一)>>>
vue3将不再支持使用数字 (即键码) 作为 v-on 修饰符,不再支持 config.keyCodes
在 Vue 2 中,keyCodes 可以作为修改 v-on 方法的一种方式。
<!-- 键码版本 -->
<input v-on:keyup.13="submit" />
此外,也可以通过全局的 config.keyCodes 选项定义自己的别名。
Vue.config.keyCodes = {
f1: 112
}
<!-- 键码版本 -->
<input v-on:keyup.112="showHelpText" />
<!-- 自定义别名版本 -->
<input v-on:keyup.f1="showHelpText" />
在 Vue 3 使用keycode修饰词将会报错:’KeyboardEvent.keyCode’ modifier on ‘v-on’ directive is deprecated. Using ‘KeyboardEvent.key’ instead‘
替代方案使用:KeyboardEvent.key
<!-- 别名版本 -->
<input v-on:keyup.enter="submit" />
在vue3,事件监听器现在是 $attrs 对象的一部分,所以 $listeners 对象在 Vue 3 中已被移除。
在 Vue 2 中,你可以通过 this. $attrs 访问传递给组件的 attribute,以及通过 this. $listeners 访问传递给组件的事件监听器
在 Vue 3 的虚拟 DOM 中,事件监听器现在只是以 on 为前缀的 attribute,这样它就成为了 $attrs 对象的一部分,因此 $listeners 被移除了。
如果这个组件接收一个 id attribute 和一个 v-on:close 监听器,那么 $attrs 对象现在将如下所示:
v2:
{
id: 'my-input',
}
v3:
{
id: 'my-input',
onClose: () => console.log('close 事件被触发')
}
在 Vue 2.x 中,当挂载一个具有 template 的应用时,被渲染的内容会替换我们要挂载的目标元素。在 Vue 3.x 中,被渲染的应用会作为子元素插入,从而替换目标元素的 innerHTML。
挂载一个应用template:
<div id="rendered">{{ message }}</div>
原页面:
<body>
<div id="app">
Some app content
div>
body>
v2渲染结果:
<body>
<div id="rendered">Hello Vue!div>
body>
v3渲染结果:
<body>
<div id="app" data-v-app="">
<div id="rendered">Hello Vue!div>
div>
body>
propsData 选项之前用于在创建 Vue 实例的过程中传入 prop,现在它被移除了。如果想为 Vue 3 应用的根组件传入 prop,请使用 createApp 的第二个参数。
v2:
const Comp = Vue.extend({
props: ['username'],
template: '{{ username }}'
})
new Comp({
propsData: {
username: 'Evan'
}
})
v3:
const app = createApp(
{
props: ['username'],
template: '{{ username }}'
},
{ username: 'Evan' }
)
现在 Vue 3 生成 prop 默认值的工厂函数不再能访问 this。
取而代之的是:
组件接收到的原始 prop 将作为参数传递给默认函数;
inject API 可以在默认函数中使用。
import { inject } from 'vue'
export default {
props: {
theme: {
default (props) {
// `props` 是传递给组件的、
// 在任何类型/默认强制转换之前的原始值,
// 也可以使用 `inject` 来访问注入的 property
return inject('theme', 'default-theme')
}
}
}
}
在 2.x 中,render 函数会自动接收 h 函数 (它是 createElement 的惯用别名) 作为参数:
// Vue 2 渲染函数示例
export default {
render(h) {
return h('div')
}
}
在 3.x 中,h 函数现在是全局导入的,而不是作为参数自动传递。
// Vue 3 渲染函数示例
import { h } from 'vue'
export default {
render() {
return h('div')
}
}
在 2.x 中,render 函数自动接收参数,如 h 函数。
// Vue 2 渲染函数示例
export default {
render(h) {
return h('div')
}
}
在 3.x 中,由于 render 函数不再接收任何参数,它将主要在 setup() 函数内部使用。这还有一个好处:可以访问在作用域中声明的响应式状态和函数,以及传递给 setup() 的参数。
import { h, reactive } from 'vue'
export default {
setup(props, { slots, attrs, emit }) {
const state = reactive({
count: 0
})
function increment() {
state.count++
}
// 返回渲染函数
return () =>
h(
'div',
{
onClick: increment
},
state.count
)
}
}
在 2.x 中,domProps 包含 VNode prop 中的嵌套列表:
// 2.x
{
staticClass: 'button',
class: { 'is-outlined': isOutlined },
staticStyle: { color: '#34495E' },
style: { backgroundColor: buttonColor },
attrs: { id: 'submit' },
domProps: { innerHTML: '' },
on: { click: submitForm },
key: 'submit-button'
}
在 3.x 中,整个 VNode prop 的结构都是扁平的。使用上面的例子,来看看它现在的样子。
// 3.x 语法
{
class: ['button', { 'is-outlined': isOutlined }],
style: [{ color: '#34495E' }, { backgroundColor: buttonColor }],
id: 'submit',
innerHTML: '',
onClick: submitForm,
key: 'submit-button'
}
在vue3,this. $slots 现在将插槽作为函数公开、且移除了 this. $scopedSlots
v2:
当使用渲染函数,即 h 时,2.x 曾经在内容节点上定义 slot 数据 property。
// 2.x 语法
h(LayoutComponent, [
h('div', { slot: 'header' }, this.header),
h('div', { slot: 'content' }, this.content)
])
此外,可以使用以下语法引用作用域插槽:
// 2.x 语法
this.$scopedSlots.header
v3:
// 3.x Syntax
h(LayoutComponent, {}, {
header: () => h('div', this.header),
content: () => h('div', this.content)
})
当你需要以编程方式引用作用域插槽时,它们现在被统一到 $slots 选项中了。
// 2.x 语法
this.$scopedSlots.header
// 3.x 语法
this.$slots.header()
Suspense 是一个试验性的新特性,其 API 可能随时会发生变动。
官方也提醒到:生产环境请勿使用
所以这个就简单了解下就行了
该 组件提供了另一个方案,允许将等待过程提升到组件树中处理,而不是在单个组件中。 组件有两个插槽。它们都只接收一个直接子节点。default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点。
在vue3, 过渡类名 v-enter 修改为 v-enter-from、过渡类名 v-leave 修改为 v-leave-from。
组件的相关 prop 名称也发生了变化:
leave-class 已经被重命名为 leave-from-class (在渲染函数或 JSX 中可以写为:leaveFromClass)
enter-class 已经被重命名为 enter-from-class (在渲染函数或 JSX 中可以写为:enterFromClass)
v2过渡类:
.v-enter,
.v-leave-to {
opacity: 0;
}
.v-leave,
.v-enter-to {
opacity: 1;
}
v3过渡类:
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-leave-from,
.v-enter-to {
opacity: 1;
}
在 Vue 2 中,通过使用 作为一个组件的根节点,过渡效果存在从组件外部触发的可能性:
<template>
<transition>
<div class="modal"><slot/>div>
transition>
template>
<modal v-if="showModal">hellomodal>
切换 showModal 的值将会在模态组件内部触发一个过渡效果。
但在 Vue 3 ,当使用
作为根结点的组件从外部被切换时将不再触发过渡效果。取而代之,你可以向组件传递一个 prop 来触发组件内过渡效果。
现在 Vue 3 中
不再默认渲染根元素,但仍然可以用 tag attribute 创建根元素。
在 Vue 2 中,
像其它自定义组件一样,需要一个根元素。默认的根元素是一个 ,但可以通过 tag attribute 定制。
<transition-group tag="ul">
<li v-for="item in items" :key="item">
{{ item }}
li>
transition-group>
在 Vue 3 中,我们有了片段的支持,因此组件不再需要根节点。所以,
不再默认渲染根节点。
如果像上面的示例一样,已经在 Vue 2 代码中定义了 tag attribute,那么一切都会和之前一样
v-on 的 .native 修饰符已被移除。同时,新增的 emits 选项允许子组件定义真正会被触发的事件。
因此,对于子组件中未被定义为组件触发的所有事件监听器,Vue 现在将把它们作为原生事件监听器添加到子组件的根元素中 (除非在子组件的选项中设置了 inheritAttrs: false)。
<my-component
v-on:close="handleComponentEvent"
v-on:click="handleNativeClickEvent"
/>
MyComponent.vue:
<script>
export default {
emits: ['close']
}
script>
在vue3用于自定义组件时,v-model prop 和事件默认名称已更改:
prop:value -> modelValue;
事件:input -> update:modelValue;
v-bind 的 .sync 修饰符和组件的 model 选项已移除
v2:
如果想要更改 prop 或事件名称,则需要在 ChildComponent 组件中添加 model 选项:
<ChildComponent v-model="pageTitle" />
// ChildComponent.vue
export default {
model: {
prop: 'title',
event: 'change'
},
props: {
// 这将允许 `value` 属性用于其他用途
value: String,
// 使用 `title` 代替 `value` 作为 model 的 prop
title: {
type: String,
default: 'Default title'
}
}
}
所以,在这个例子中 v-model 是以下的简写:
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
v3:
在 3.x 中,自定义组件上的 v-model 相当于传递了 modelValue prop 并接收抛出的 update:modelValue 事件。若需要更改 model 的名称,现在我们可以为 v-model 传递一个参数,以作为组件内 model 选项的替代:
<ChildComponent v-model:title="pageTitle" />
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
v2:
2.x 版本中在一个元素上同时使用 v-if 和 v-for 时,v-for 会优先作用。
v3:
3.x 版本中 v-if 总是优先于 v-for 生效。
v2:
在 2.x 中,如果一个元素同时定义了 v-bind=“object” 和一个相同的独立 attribute,那么这个独立 attribute 总是会覆盖 object 中的绑定。
<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="red"></div>
v3:
在 3.x 中,如果一个元素同时定义了 v-bind=“object” 和一个相同的独立 attribute,那么绑定的声明顺序将决定它们如何被合并。后定义的属性会覆盖前定义的结果。
<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="blue"></div>
<!-- 模板 -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- 结果 -->
<div id="red"></div>
在 Vue 2 中,我们可以通过事件来监听组件生命周期中的关键阶段。这些事件名都是以 hook: 前缀开头,并跟随相应的生命周期钩子的名字。
在 Vue 3 中,这个前缀已被更改为 vnode-。额外地,这些事件现在也可用于 HTML 元素,和在组件上的用法一样。
v2:
在 Vue 2 中,这些事件名和相应的生命周期钩子一致,并带有 hook: 前缀:
<template>
<child-component @hook:updated="onUpdated">
template>
v3:
在 Vue 3 中,事件名附带的是 vnode- 前缀:
<template>
<child-component @vnode-updated="onUpdated">
template>
在Vue3中,当使用 watch 选项侦听数组时,只有在数组被替换时才会触发回调。换句话说,在数组被改变时侦听回调将不再被触发。要想在数组被改变时触发侦听回调,必须指定 deep 选项。
watch: {
bookList: {
handler(val, oldVal) {
console.log('book list changed')
},
deep: true
},
}
上一章:Vue3较Vue2的更新内容(一)>>>