vue2和vue3的响应式数据原理和区别

vue2 VS vu3区别:
一、默认进行懒观察(lazy observation)
  在 2.x 版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,这可能会在页面载入时造成明显的性能压力。3.x 版本,只会对「被用于渲染初始可见部分的数据」创建观察者,而且 3.x 的观察者更高效。

二、更精准的变更通知。

举例来说:2.x 版本中,使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行;3.x 版本中,只有依赖那个属性的 watcher 才会重新运行。
三、vue3 的template可以支持多个子元素
四、vue3的生命周期 setup(){}替换 beforecreate和created()在这里插入图片描述

五、3.0里也取消了data(), 引用了Reactive():声明单一对象时使用, ref():声明单一基础数据类型时使用
六、
main.js
createApp(App).use(router).use(store).mount(‘#app’)
vuex

// vue2.x vuex
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
}

// vue3.x vuex
import Vuex from 'vuex'

export default Vuex.createStore({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
})

<template>
</template>
<script lang="ts">
import { defineComponent, setup } from 'vue'
export default defineComponent({
   setup(props, context) {
       //这里的props大家应该知道是啥吧,父组件传的值
       // context是什么?
       //在setup()里我们不能用this
       //所以vue2.0里的 this.$emit, this.$psrent, this.$refs在这里都不能用了。
       //context就是对这些参数的集合
       //context.attrs
       //context.slots
       //context.parent 相当于2.0里 this.$psrent
       //context.root 相当于2.0里 this
       //context.emit 相当于2.0里 this.$emit
       //context.refs 相当于2.0里 this.$refs
       ...
   }
})
</script>
<style>
</style>

五、vue3的生命

vue3用Proxy的优势如下

  1. 可以直接监听整个对象而非属性。
  2. 可以直接监听数组的变化。
  3. 有13中拦截方法,如ownKeys、deleteProperty、has 等是 Object.defineProperty 不具备的。
  4. 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;

Object.defineProperty 的优势如下

兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平。
Object.defineProperty 不足在于:

Object.defineProperty 只能劫持对象的属性(key值.Object.key()),因此我们需要对每个对象的每个属性进行遍历。
Object.defineProperty不能监听数组。是通过重写数据的那7个可以改变数据的方法来对数组进行监听的。
Object.defineProperty 也不能对 es6 新产生的 Map,Set 这些数据结构做出监听。
Object.defineProperty也不能监听新增和删除操作,通过 Vue.set()和 Vue.delete来实现响应式的。


vue2用defineProperty({},key,handel)
缺点:Object.defineProperty() 无法监控到数组下标的变化,对象的增加。对于新增加的属性,需要再手动初始化才能被监测。通过 Vue.set()和 Vue.delete来实现响应式的。
需要重新执行observe(arr),遍历,影响性能。

let obj = {
  name: '李四',
  address: '上海浦东新区',
  flags: {
    book: {
      page: 153,
      name: 'JS'
    },
    hobby: ['足球', '游戏', '音乐']
  }
}
function observer(obj) {
  if (typeof obj == 'object') {
    for (let key in obj) {
      defineReactive(obj, key, obj[key])
    }
  }
}
 
function defineReactive(obj, key, value) {
  Object.defineProperty(obj, key, {
    get() {
      console.log('获取:' + key)
      return value
    },
    set(val) {
      observer(val)
      console.log(key + "-数据改变了")
      value = val
    }
  })
}
 
observer(obj)

极简的响应数据,vue2的方法

const obj = {};
Object.defineProperty(obj, 'text', {
  get: function() {
    console.log('get val'); 
  },
  set: function(newVal) {
    console.log('set val:' + newVal);
    document.getElementById('input').value = newVal;
    document.getElementById('span').innerHTML = newVal;
  }
});

const input = document.getElementById('input');
input.addEventListener('keyup', function(e){
  obj.text = e.target.value;
})

vue3用proxy代理

  1. 没有任何拦截
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"
let obj = {
      name: '李四',
      address: '上海浦东新区',
      flags: {
        book: {
          page: 153,
          name: 'JS'
        },
        hobby: ['足球', '游戏', '音乐']
      }
    }
 
 
    function observerProxy(obj) {
      const handler = {
        get(target, key, receiver) {
          console.log('获取:' + key) // 如果是对象,就递归添加 proxy 拦截
          if (typeof target[key] === 'object' && target[key] !== null) {
            return new Proxy(target[key], handler)
          }
          return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver) {
          console.log('设置:' + key) // 如果是对象,就递归添加 proxy 拦截
          return Reflect.set(target, key, value, receiver)
        }
      }
      return new Proxy(obj, handler)
    }
 
    let newObj = observerProxy(obj)

1.Object.defineProperty 拦截的是对象的属性,会改变原对象。proxy 是拦截整个对象,通过 new 生成一个新对象,不会改变原对象。

2.proxy 的拦截方式,除了上面的 get 和 set ,还有 11 种。选择的方式很多 Proxy,也可以监听一些 Object.defineProperty 监听不到的操作,比如监听数组,监听对象属性的新增,删除等。

get(target, propKey, receiver)
set(target, propKey, value, receiver)
has(target, propKey)
deleteProperty(target, propKey)
ownKeys(target)
getOwnPropertyDescriptor(target, propKey)
defineProperty(target, propKey, propDesc)
preventExtensions(target)
getPrototypeOf(target)
isExtensible(target)
setPrototypeOf(target, proto)
apply(target, object, args)
construct(target, args)

this.$forceUpdate();
还有给对象或数组赋值可以用vue中的 $set

调用方法:this.$set( target, key, value )

🌹 target:要更改的数据源(可以是对象或者数组)

🌹 key:要更改的具体数据

🌹 value :重新赋的值

参考:
https://www.cnblogs.com/weblff/p/14144414.html

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端段

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值