1. 全局API
可以看到,在Vue2中我们使用new Vue() 方式简单的创建了一个 Vue 的根实例, 而在Vue3中我们使用新的global API创建,即使用 createApp() 创建。Vue2在根上创建固然简单,但是使用可能会引起污染。所以 Vue3 使用实例创建,如果想要使用其他方法,为避免污染,可以新创建一个实例,将需要的方法绑定到新实例上即可。
2. v-model双向绑定
prop: value -> modelValue;
event: input -> update:modelValue
v-bind的sync修饰符以及model 选项被移除了,使用 v-model 代替。此外,在同一个组件上可以绑定多个 v-model,还可以自定义 v-model 修饰符。
3. v-if & template
v-if/v-else/v-else-if 移除了 key 值,template 使用 v-for 后,将 key 属性放到 template 上即可,而不需要放到它的子节点上。
4. v-if & v-for
如果在同一个元素上同时使用,v-if 将比 v-for 有更高的优先级。
5. v-bind 合并
在 vue2 中,v-bind 和相同属性值同时存在,单独的属性值会一直覆盖掉 v-bind 中的对象值。在 vue3 中,跟书写的顺序有关,后面的会替换掉前面的。
6. native修饰符
v-on.native 修饰符被移除。与此同时,emits 参数允许子组件定义的确需要传递的事件。
7. 渲染函数
7.1 组件参数
Vue2的渲染函数有3个参数:props、data、children;3变成了两个参数:props、context,listeners 被添加到了 attrs 属性中,已经被移除。 Vue2的:
Vue3:
7.2 同步组件
- 新的方法 defineAsyncComponent 显示定义同步组件
- 组件选项重命名为 loader
- 加载函数并不继承接收 resolve 和 reject 参数,而是必须要返回一个 Promise 对象。
7.3 emits
Vue3 中的 emits 事件需要声明,用法和 props 相同,可以定义为数组和对象,定义为对象时增加了验证。
父组件在执行子组件 emits 的事件时,会执行两次:一次是原生的;另外一次是父组件监听后执行的事件。为解决这个问题,有两种方法:1. 在正确的地方声明点击事件;2. 子组件移除 emits 事件。
8. 插槽
- this.$slots 被作为一个函数暴露出去
- this.$scopedSlots 被移除
9. attrs 包含 class 和 style
10. teleport & suspence
11. setup
在 script 中声明为 setup 语法后,不需要使用 data、methods 等方式声明了,直接定义即可。
12. Fragment
在使用 template 模板时,可以包含多个一级元素节点了
13. 生命周期钩子
-
Vue2:
- beforeCreate
- created
- beforeMount
- mounted
- updated
- beforeDestroy
- destroyed
- errorCaptured
- activated
- deactivated
-
Vue3:
- onBeforeMount
- onMounted
- onBeforeUpdate
- onUpdated
- onBeforeUnmount
- onUnmounted
- onErrorCaptured
- onActivated
- onDeactivated
14. 响应式原理
vue2的响应式原理是靠 Object.defineProperty 实现的,vue3 是通过 Proxy 来实现的。
vue2:
-
需要提前递归地遍历 data 做到响应式
-
无法跟踪到对象增加新值,删除属性
- 因为 Object.defineProperty 是属性层级的api。只能拦截对象的某个属性,所以只能遍历需要监听对象的属性来跟踪。因此监听不了新增属性。
- 而 Object.defineProperty api本身无法跟踪对象删除属性,所以 Vue2 中,提供了 delete。
-
数组需要额外处理
- 数组处理思想:创建一个指向 Array.prototype 的对象,在这个对象中创建 vue2 中那七个 api 属性。其每个属性是调用 Array.prototype 上的 api,同时可实现跟踪。最后,将监听的数组使其原型指向这个创建的对象。
function trackArray(arr) { const prototype = Array.prototype const newProto = Object.create(prototype) const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'] methods.forEach(item => { newProto[item] = function(...args) { prototype[item].call(arr, ...args) console.log('call ', item) } }) arr.__proto__ = newProto }
vue3:
- 可以很完备的监听到属性增加和删除
- 数组可以使用原生api,不需要再对需要监听的api做单独处理
- 在获取值的时候才对其进行监听(按需监听)
- 使用 Proxy 可以解决 vue2 出现的问题
具体可以可以查看此文章