vue3相比vue2有哪些变化?
- API和数据响应式的变化
- 去除构造函数
- 组件实例中的API
- 响应式的变化
- 生命周期
- Vue3新增
- 模板中的变化
- v-model与.sync修饰符
- v-for和v-if
- key
- Fragment
- 组件的变化
- 异步组件
- 可自行更改组件结构
API和数据响应式的变化
去除构造函数
在vue2中,当一个页面需要多个vue应用时,在需要插件的场景下,会导致多个应用都挂载了相同的插件,因为插件的注册是在new vue之前,即挂载在vue的原型上。
Vue.use(XXX)
Vue.mixin(XXX)
new Vue({}).$mount('#app1')
new Vue({}).$mount('#app2')
在vue3中,去除了构造函数,转而使用createApp的方法创建vue应用,可以链式调用。
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).use(XXX).mount('#app1')
createApp(App).mount('#app2')
vue3去除构造函数大概是以下几点原因:
- 构造函数的形式不利于隔离不同的应用。调用构造函数的静态方法会对所有vue应用生效。
- 构造函数的形式不利于tree shaking,vue2的构造函数集成了太多功能,vue3把这些功能使用普通的函数导出,这样有利于tree shaking优化打包体积。
- vue2 在设计上没有把组件实例和vue应用这两个概念区分开,在vue2中,通过new Vue创建的对象,既是一个vue应用,同时又是一个特殊的组件。vue3中,把这两个概念区分开来,通过createApp创建的对象,是一个vue应用,它内部提供的方法是针对整个应用,而不再是一个特殊的组件。(vue2中,new Vue之后的对象有着很多组件身上的方法)
组件实例中的API
vue3的组件实例是一个Proxy,它有着和vue2一样的大多数方法。只是vue3的组件实例身上的方法会比vue2少很多,因为是通过Proxy代理,所以不该被开发者访问的方法,Proxy并不会返回,所以vue3在成员方法上会比vue2少很多。
<script>
export default {
created(){
console.log(this)//组件实例是一个Proxy
}
}
</script>
响应式的变化
vue2和vue3都是在相同的生命周期(beforeCreate之后、created之前)完成数据的响应式。
实现上,vue2使用Object.defineProperty完成数据的响应式,在对象里使用递归,当树的层级较深时,需要耗费一定的性能,而且在某些情况下并不能做到对某些数据进行响应式监听,所以需要 s e t 、 set、 set、delete方法处理。
而vue3使用Proxy代理数据,无需遍历对象,直接new Proxy即可完成数据的响应式处理。而且并不会存在新增数据删除数据监听不到的情况,所以vue3并没有$set、$delete的方法,新增数据、删除数据、索引访问等均可触发响应式处理。
生命周期
Vue3新增
vue3新增了Reactivity API 和Composition API,setup语法糖等。
setup使得我们编写代码更加灵活。
Reactivity API
Composition API
模板中的变化
v-model与.sync修饰符
vue2双向数据绑定的方法有两种,v-model和.sync。
在vue3中,去掉了.sync修饰符,在vue3使用.sync会出现以下警告(’.sync’ modifier on ‘v-bind’ directive is deprecated. Use ‘v-model:propName’ instead.),只有v-model这个方法可以进行双向绑定。
vue3对v-model做了以下修改:
- 当对自定义组件使用v-model时,绑定的属性名由原来的value变为modelValue,事件名由原来的input变为update:modelValue。
//vue2
<my-component :value="myValue" @input="handleInput" />
//vue2-简写
<my-component v-model="myValue" />
//vue3
<my-component :modelValue="myValue" @update:modelValue="handleModel" />
//vue3-简写
<my-compoonent v-model="myValue" />
- 去掉了.sync修饰符,它原本的功能由v-model参数代替。
//vue2
<my-component :value="myValue" @update:value="myValue = $event" />
//vue2-简写
<my-component :value.sync="myValue" />
//vue3
<my-component :value="myValue" @update:value="myValue = $event" />
//vue3-简写
<my-compoonent v-model:value="myValue" />
- vue3里,mode配置被移除
- vue3相比vue2,新增了自定义v-model修饰符
//父组件
<Comp v-model.cap="data1" v-model:text.cap="data2" />
//子组件
//自定义的v-model修饰符会放在props的[propName]Modifiers里,其数据是一个对象,包含了传进来的修饰符
props:{
textModifiers:{
default:()=>{}
}
}
v-for和v-if
vue2中v-for优先级高于v-if,虽然vue2规范中不建议v-for和v-if同写一行,因为在循环中+判断这样会带来性能问题。
vue3中v-if优先级高于v-for,因为vue3觉得vue2既然不推荐v-for和v-if同行,那设置优先级本身没有什么意义。
key
- 当使用<template>进行v-for时,vue3需要把key放在<template>,而不是把key放在子元素中。(vue2是把key放在子元素)。
- 当使用v-if、v-else-if、v-else不再需要使用key,因为vue3会自动给予每个分支一个唯一的key。
Fragment
vue3允许组件出现多个根节点,同react的Fragment会生成虚拟的根节点。
组件的变化
异步组件
defineAsyncComponent可以创建一个只有在需要时才会加载的异步组件。
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent({
// 工厂函数
loader: () => import('./Foo.vue'),
// 加载异步组件时要使用的组件
loadingComponent: LoadingComponent,
// 加载失败时要使用的组件
errorComponent: ErrorComponent,
// 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
delay: 200,
// 如果提供了 timeout ,并且加载组件的时间超过了设定值,将显示错误组件
// 默认值:Infinity(即永不超时,单位 ms)
timeout: 3000,
// 定义组件是否可挂起 | 默认值:true
suspensible: false,
/**
*
* @param {*} error 错误信息对象
* @param {*} retry 一个函数,用于指示当 promise 加载器 reject 时,加载器是否应该重试
* @param {*} fail 一个函数,指示加载程序结束退出
* @param {*} attempts 允许的最大重试次数
*/
onError(error, retry, fail, attempts) {
if (error.message.match(/fetch/) && attempts <= 3) {
// 请求发生错误时重试,最多可尝试 3 次
retry()
} else {
// 注意,retry/fail 就像 promise 的 resolve/reject 一样:
// 必须调用其中一个才能继续错误处理。
fail()
}
}
})
试验性的Suspense,Suspense 是一个试验性的新特性,其 API 可能随时会发生变动。
该 <suspense> 组件提供了另一个方案,允许将等待过程提升到组件树中处理,而不是在单个组件中。
<suspense> 组件有两个插槽。它们都只接收一个直接子节点。default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点。
<template>
<suspense>
<template #default>
<todo-list />
</template>
<template #fallback>
<div>
Loading...
</div>
</template>
</suspense>
</template>
<script>
export default {
components: {
TodoList: defineAsyncComponent(() => import('./TodoList.vue'))
}
}
</script>
可自行更改组件结构
<teleport>可以将组件元素嵌套在另一个元素内部,以构建一个组成应用程序 UI 的树。
有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置
以蒙层功能为例,我们可以在组件内部将其插入到body里。
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})
更多推荐
vue3相比vue2有哪些变化?
发布评论