vue 是如何深度监听data的变化的

调用observer函数,传入data,observer(data),遍历data每一个属性,调用defineReactive(target,key,target[key]),defineReactive里通过Object.defineProperty 对target 上的key属性进行get、set的拦截,在set里触发视图更新
// 设置数据劫持,设置数据响应式
function defineReactive(target,key,target[key]){
    // 深度监听 
    observer(value);
   // 核心 API 
    Object.defineProperty(target,key,{
        get(){
            return value
        },
        set(newValue){
            if(newValue!==value){
               // 深度监听 
                observer(value)
                value=newValue;
                // 触发更新 
                updateView()
            }
        }
    })
}

// 监听data属性
function observer(target){
    if(typeof target !== 'object' || target===null){
      // 不是对象或者数组,直接返回
      return target;
  }
    // 如果是数组,更改该对象的原型
    if (Array.isArray(target)) {
        target.__proto__ = arrProto;
    }
  for(let key in target){
    defineReactive(target,key,target[key])
  }
}

// 更新视图
function updateView(){
  console.log("更新视图")
}

const data = {
  name:"Lili",
  age:20
}

observer(data)
如何实现数组的监听

1、重写数组原型方法
2、observer 函数中,若属性为数组,则更改数组属性的proto为重写后的数组对象

// 重新定义数组原型
function reWriteArrayProperty() {
    const oldArrayProperty = Array.prototype;
    const arrProto = Object.create(oldArrayProperty);
    ['push', 'pop', 'shift', 'unshift', 'splice'].forEach((key) => {
        arrProto[key] = function () {
            updateView();
            oldArrayProperty[key].call(this, ...arguments);
        };
    });
    return arrProto;
}

// 监听data属性
function observer(target) {
    if (typeof target !== 'object' || target === null) {
        // 不是对象或者数组,直接返回
        return target;
    }
    
    // 如果是数组,更改该对象的原型
    if (Array.isArray(target)) {
        target.__proto__ = reWriteArrayProperty();
    }
    
    for (let key in target) {
        defineReactive(target, key, target[key]);
    }
}

Object.defineProperty 的缺点

1、深度监听,需要递归到底,一次性计算量大
2、新增属性、删除属性,监听不到
3、无法监听数组,需要改写数组原生方法,然后改变数组的原型

data.x = 2;  // 监听不到属性x的新增,Vue.set
delete data.x ;  // 监听不到属性x的删除,Vue.delete

你可能感兴趣的:(vue 是如何深度监听data的变化的)