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()vue2和vue3的响应式数据原理和区别_第1张图片

五、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: {}
})





五、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

你可能感兴趣的:(js学习,vue学习,vue.js,前端,javascript)