vue2 和 vue3 对比
一、Vue3的优点
- 1、diff算法的提升
vue2中的虚拟DOM是全量的对比,也就是不管是写死的还是动态节点都会一层层比较,浪费时间在静态节点上。
vue3新增静态标记(patchflag ),与之前虚拟节点对比,只对比带有patch flag 的节点,可通过flag信息得知当前节点要对比的具体内容。
例如: 当代码中包含数据时,会标记为动态。
- 2、静态提升
vue2不管是否参与更新,都会重新创建再渲染。
vue3对于不参与更新的元素,会做静态提升,只被创建一次,在渲染时直接复用即可。
- 3、事件侦听器缓存。
- 4、 ssr渲染
- 5、更好的ts支持
- 6、Composition Api
vue2的组件内部都是options api风格,也就是在data, methods, mounted等来组织代码,这样会让逻辑很分散,每次变动需要反复查找位置。
vue3中使用setup,逻辑都放到里边。
- 7、更先进的组件
vue2不允许template下写两个组件,vue3允许,将为我们创建一个虚拟的Fragment节点。
- 8、自定义渲染api
const { createApp } from 'vue' import App from "./src/App" createApp(App).mount(('#app')
- 9、按需编译,体积比vue2更小
- 10.支持多根节点组件
二、响应式原理不同:
- vue2实现双向数据绑定原理,是通过ES5的Object.defineProperty,根据具体的key去读取和修改。其中的setter方法来实现数据劫持,getter实现数据修改。但是必须要先知道拦截和修改的key,所以vue2对于新增的属性无能为力,比如无法监听属性的新增和删除,数组索引和长度的变更,解决方法使用Vue.set(object, properName,value)等嵌套对象添加响应式。
function observe(obj, callback) { let newObj = {}; Object.keys(obj).forEach((key) => { Object.defineProperty(newObj, key, { enumerable: true, configurable: true, get() { return obj[key]; }, set(val) { obj[key] = val; callback(key, val); } }) }) return newObj; } let obj = observe({ name: 'alan', age: '1888' }, (key, value) => { console.log(`打印${value}`) });
- 在vue3中使用es5中得更快的proxy,替代了Object.defineProperty。proxy可以理解为在对象外加了一层拦截,任何人要访问该对象,都要通过这层拦截。且proxy直接对对象拦截而非属性,并返回一个对象,具有更好的响应式支持。
function obseve2(obj, callback) { return new Proxy(obj, { set(target, key, value) { target[key] = value; callback(key, value); }, get(taget, key) { return taget[key]; } } ) } let obj2 = obseve2({ x: 1, y: 2 }, (key, value) => { console.log('坐标系') })
三、生命周期变化
初始化加载顺序:
setup
=> beforeCreate
=> created
=> onBeforeMount
=> onMounted
vue3压缩后变快,很大程度是因为这些使用都需要引入了。
!!! vue3中的核心api都支持了tree-shaking,这些api都是通过包引入的方式而不是直接在实例化时就注入,只会对使用到的功能或特性进行打包(按需打包),这意味着更多的功能和更小的体积。
四、mixins更改
在vue2 使用mixins来实现相同逻辑的抽离,每个组件只需要引入mixins,就能实现复用。
创建js文件,写入
export default { data(){ return {} }, methods:{}, computed:{}, filters:{}, created(){}, mounted(){ console.log("我是mixins"); } }
使用方法:
引入js文件,写入mixins:[ ]
缺点:mixins的声明周期会和引入mixins的组件的生命周期整合在一起。且minxins的生命周期比组件调用快。组件的data,methods会覆盖同名data,methods。
1.变量来源不明确(隐式传入),不利于阅读,使代码变得难以维护。
2.多个mixins的生命周期会融合到一起运行,但是同名属性、同名方法无法融合,可能会导致冲突。
3.mixins和组件可能出现多对多的关系,复杂度较高(即一个组件可以引用多个mixins,一个mixins也可以被多个组件引用)。
vue3中的改进:
自定义hook的作用类似vue2的mixin,封装可复用的功能函数。
import { ref,computed } from "vue"; export function useCount(){ const num = ref(10); const doubles = computed(() => num.value * 2); return { num, doubles } }
import {useCount} from './useCount' //初始化 const {num,doubles}=useCount();
五、父子传值的变化
在vue2中使用props传值。
在vue3中依旧使用,但是传值写法有所变化。
vue3 父组件
<page2 :name="ageRef" @clickParent="clickParent"></page2> function clickParent() { console.log('我想点击父组件') }
子组件
<template> <div> 我是子组件page2啊: <div @click="emitP">{{name}}</div> </div> </template> <script> import { toRefs } from 'vue' export default{ props:{ name: String, }, setup(props,context){ let {name}=toRefs(props); let {slots,emit}=context; function emitP(){ emit('clickParent'); } return{ name, emitP } } } </script>
context:
包含 attrs
, slots
, emit
等数据方法:
attrs
:获取组件上的属性slots
:获取 slot 插槽的节点emit
:emit 方法(子组件向父组件传递数据)
setup 函数是 Vue3 中新增的一个生命周期函数,会在 beforeCreate
之前调用。因为此时组件的 data
和 methods
还没有初始化,因此在 setup 中是不能使用 this
的。所以 Vue 为了避免我们错误的使用,它直接将 setup 函数中的 this
修改成了undefined
。并且,我们只能同步使用setup函数,不能用async将其设为异步。
setup 函数接收两个参数 props
和 context
, 语法为:setup(props,context){}
props
props
里面包含父组件传递给子组件的所有数据。在子组件中使用 props
进行接收。
props
是响应式的, 当传入新的 props
时,会及时被更新。
由于是响应式的, 所以不可以使用 ES6 解构,解构会消除它的响应式。可以使用toRefs
provide,inject 父组件向子组件传递方法和数据
api均从vue中引入。
在父组件直接provide(‘别名’,变量或方法);
在子组件直接inject(‘别名’)
六、碎片化节点
在vue2中,template下只允许存在一个根节点,在vue3中可以有多个跟结点。
参考文章:
https://www.cnblogs.com/bingcola/p/15210566.html