浅谈一下vue2和vue3的区别

500 阅读2分钟

简介

vue3现在越来越多公司开始普及,现在就来谈谈他们的区别吧!

区别

一.响应式原理发生了变化

vue2双向数据绑定是利用ES5的Object.defineProperty()对数据进行劫持,结合发布订阅模式来实现

vue3中使用ES6ProxyAPI对数据代理

它们的响应式实现代码雏形如下:

// vue2实现响应式
let person1 = { name: "张三" }
let p1 = { age: '', sex: '', count: '', info: { xx1: '', xx2: '', xx3: '' } }

// 递归为对象属性添加响应式
function objDefineProperty(obj) {
  // 如果不是对象则直接返回
  if (typeof obj !== 'object' || obj === null) {
    return
  }
  
  Object.keys(obj).forEach(key => {
    // 递归处理嵌套对象
    if (obj[key] && typeof obj[key] === 'object') {
      objDefineProperty(obj[key])
    }
    
    try {
      let value = obj[key]
      Object.defineProperty(obj, key, {
        configurable: true,
        enumerable: true,
        get() {
          console.log(`读取属性 ${key}: ${value}`)
          return value
        },
        set(newValue) {
          console.log(`设置属性 ${key}: ${newValue}`)
          // 如果新值是对象,也需要递归处理
          if (newValue && typeof newValue === 'object') {
            objDefineProperty(newValue)
          }
          value = newValue
        }
      })
    } catch (error) {
      console.error(`处理属性 ${key} 时出错:`, error)
    }
  })
}

function setDefineProperty(p) {
  Object.keys(p).forEach(key => {
    if (p[key] && typeof p[key] === "object") {
      objDefineProperty(p[key])
    }
    try {
      Object.defineProperty(p, key, {
        configurable: true,
        // 读取属性值时触发
        get() {
          return person[key]
        },
        // 设置属性值时触发
        set(value) {
          person1[key] = value
        }
      })
    } catch (error) {
        console.log(error)
    }
  })
}
setDefineProperty(p1)


// vue3实现响应式
let person2 = { name: "李四" }
let p2 = new Proxy(person2, {
  // 读取属性值时触发
  get: function (target, attr) {
    return Reflect.get(target[attr]);
  },
  // 设置属性值时触发 【与vue2不同的是,这里给对象或数组添加属性时同样会触发set】
  set: function (target, attr, value) {
    Reflect.set(target, attr, value)
  },
  // 移除属性的时候触发
  deleteProperty: function (target, attr) {
    return Reflect.deleteProperty(target, attr);
  },
});
    

经过控制台调试发现: vue2添加属性或者移除属性的时候,Object.defineProperty会劫持不到。

造成的痛点:

1、造成了vue2中很多时候明明数据变化了,但是页面会响应不到。导致需要用 this.$set(target, key, value) 、Object.assign、splice等方法去解决该问题。

2、对象层级过多的情况下,vue2处理页面响应太过麻烦。而vue3中默认监听多层,也可通过shallowReactive只监听第一层。

二.template部分有了细微的改动

vue2中页面必须包一个根标签,vue3中不需要额外添加一个根标签,它会默认添加一个虚拟的Fragment组件到页面中。用调试工具即可看到,这样就减少了标签层级和内存占用

三.hooks代替minxins

mixins的缺点

1.变量来源不明确(隐式传入),不利于阅读,使代码变得难以维护。

2.多个mixins的生命周期会融合到一起运行,但是同名属性、同名方法无法融合,可能会导致冲突。

3.mixins和组件可能出现多对多的关系,复杂度较高(即一个组件可以引用多个mixins,一个mixins也可以被多个组件引用)。

自定义Hook优势

1、复用代码,让setup中的逻辑更清楚易懂。

2、⾃定义hook相对于普通js复⽤逻辑的抽离,然后可以在页⾯调⽤。

下面是以一个简单的计数器为例,来说明mixins和自定义hook在写法和使用上的区别。

微信截图_20220504132519.png

四.vue3对Ts的支持性比较高,TS yyds,谁用谁知道!