1.Tree-shanking
vue3引入tree-shanking(术语),通常用于描述移除js上下文中未引用的代码(dead-code)。
在vue2.x版本中,很多函数都挂载到全局vue对象上,例如set、nextTick等函数。虽然我们平时可能用不到,但打包时还是会将这些全局函数都打包到bundle中。
而vue3采用es6模块化方式引入,这样能让webpack和rollup等打包工具在打包时候对没有用到的api进行剔除,减少bundle的体积。
创建app实例的方式,由原来的new Vue()变成了createApp函数来创建。
2.生命周期函数
注意:3.0中的生命周期钩子要比2.X中相同生命周期的钩子要快
- beforeCreate -> setup
- created -> setup
- beforeMount ->onBeforeMount
- mounted ->onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforedestroy ->onBeforeUnmount
- destroyed -> onUnmounted
- activated -> onActivated
- deactivated -> onDeactivated
- erorrCaptured -> onErrorCaptured
add 调试用的debug钩子函数
- onRenderTracked
- onRenderTriggered //记录数据更新后的数据变化
3.vue的响应式原理
在vue2.x采用Object.defineProperty,而vue3使用Porxy。
4.优化点
- 向下兼容,vue3支持大多数vue2的特征。
- 性能的提升,打包减少41%,初次渲染快55%,更新更快133%,内存使用减少54%。
- 推出composition api,解决vue2中复杂组件的问题
- 其它新特性:Telport(瞬间组件)、Suspense(解决异步加载组件的问题)和全局api的修改和优化。
- 重写vdom,初始渲染/更新更快
vue3支持多个根节点,vue2只支持单节点,在vuter语法检查中会报错,但不影响使用。vue3基于proxy的响应式对象,vue2.x使用object.defineProperty()来实现响应式数据。
5.teleport
瞬移(俗称通道),提供一种干净的方,让组件的html在父组件界面外的特点标签(很可能是Body)下插入显示 换句话说就是可以把子组件或者dom节点插入到任何你想插入到的地方。
使用案例:https://juejin.cn/post/6977004323742220319
https://zhuanlan.zhihu.com/p/256349288
6.Suspense
用于异步请求的组件。
<Suspense> <template #default> <asunc-show /> //组件 ...//多组件也适用 </template> <template #fallback> //先调用,一段时间后执行上面组件 <h1>loading/h1> </template> </Suspense> //vue3引入异步组件的方式 const asuncShow = defineAsyncComponent(() => import('./asuncShow.vue')) //onErrorCaptured钩子函数可以捕获上面异步组件异常 onErrorCaptured((e:any)=>{ error.value = e; return true; })
7.vue2与vue3挂载区别
vue2全局api遇到的问题
- 单元测试中,全局配置非常容易污染全局环境
- 在不同的apps中,共享一份不同配置的Vue对象,也变得非常困难
全局配置:Vue.config -> app.config
- config.productionTip被删除
- config.ignoredElement改名为config.isCustomElement
- config.keyCodes被删除
8.watch语法的使用以及区别
多个对象监听(vue2和vue3)
9.vue3为什么要用composition api?
vue2存在一个弊端,对于公共的代码,vue2的解决方案是采用mixin来混合,这样确实拆分了砝码,但有一个很严重的问题,在文件中你不知道App.vue里的this上,这些属性是从何处来,不知道是mixin还是全局install。这是vue2的一个大问题。然后在多文件中,命名可能会冲突,那就更难找了,composition 就是为了解决这个问题存在的。
文献:https://juejin.cn/post/6891640356543627278#heading-3
10.vue自定义指令
先看看Vue2自定义指令的钩子
- bind:当指令绑定在对应元素时触发。只会触发一次。
- inserted:当对应元素被插入到 DOM 的父元素时触发。
- update:当元素更新时,这个钩子会被触发(此时元素的后代元素还没有触发更新)。
- componentUpdated:当整个组件(包括子组件)完成更新后,这个钩子触发。
- unbind:当指令被从元素上移除时,这个钩子会被触发。也只触发一次。
在 Vue3 中,官方为了更有助于代码的可读性和风格统一,把自定义指令的钩子名称改的更像是组件生命周期,尽管他们是两回事
- bind => beforeMount
- inserted => mounted
- beforeUpdate: 新的钩子,会在元素自身更新前触发
- update => 移除!
- componentUpdated => updated
- beforeUnmount: 新的钩子,当元素自身被卸载前触发
- unbind => unmounted
11.vue中钩子函数watch、computed、method的执行顺序
初始化项目时:不执行method,先执行watch然后computed,当调用方法后,先触发方法,然后在执行watch。
项目中需要点击方法时,先初始watch,然后method,这里可以通过改变成异步(加个定时器)的形式解决,如果是指令可以在指令上加.sync。
12.vue2和vue3的keepAlive区别
keepAlive:是Vue的内置组件,作用是将组件缓存在内存中,防止重复渲染DOM,属于消耗内存获取速度。
<template> <!-- vue2.x配置 --> <keep-alive> <router-view v-if="$route.meta.keepAlive" /> </keep-alive> <router-view v-if="!$route.meta.keepAlive"/> </template>
<template> <!-- vue3.0配置 --> <router-view v-slot="{ Component }"> <keep-alive> <component :is="Component" v-if="$route.meta.keepAlive"/> </keep-alive> <component :is="Component" v-if="!$route.meta.keepAlive"/> </router-view> </template>
详细配置可参考:https://blog.youkuaiyun.com/m0_46309087/article/details/109403655
13.scrollBehavior解决keepalive缓存页面位置问题
router配置,https://blog.youkuaiyun.com/q3254421/article/details/84777614,vue3暂未支持
14.vue3.0移除的一些api和方法
(1)取消keycode
//vue2.x <input v-on:keyup.13="submit" /> <!-- alias version --> <input v-on:keyup.enter="submit" /> //vue3中不支持keycode,但依旧可以使用别名 <input v-on:keyup.delete="confirmDelete" />
(2)移除on、off、$once
//vue2.x var EventBus = new Vue() Vue.prototype.$EventBus = EventBus this.$EventBus.$on() this.$EventBus.$emit() //vue3.0移除on、off等方法,推荐mitt方案,需要安装mitt import mitt from 'mitt' const emitter = mitt() // listen to an event emitter.on('foo', e => console.log('foo', e) ) // fire an event emitter.emit('foo', { a: 'b' })
(3)移除filters
filter确实是可以通过组件代替的,但是组件的性能开销似乎要大一点点。vue3.0删除filter过滤器,采用设置util调用method或者computed来替代。
//vue2.x <template> <p>{{ accountBalance | currencyUSD }}</p> </template> <script> export default { filters: { currencyUSD(value) { return '$' + value } } } </script> //vue3.0 <template> <p>{{ accountInUSD }}</p> </template> <script> export default { props: { accountBalance: { type: Number, required: true } }, computed: { accountInUSD() { return '$' + this.accountBalance } } } </script>
(4)移除inline-template
在Vue2.x中,在父组件引入子组件时,会用到inline-template来使子组件的内容也得到展示,参考这里,例如
<my-component inline-template> <div> <p>These are compiled as the component's own template.</p> <p>Not parent's transclusion content.</p> </div> </my-component>
在Vue3中,这个功能将被移除,目前inline-template使用的并不多,这里就不再过多讲解
15.render方法修改
//vue2.x export default { render(h) { return h('div') } } //vue3.0 import { h } from 'vue' export default { render() { return h('div') } }