vue响应式数据变化

vue响应式数据变化

话不多说,先上代码:

//拷贝一份数组原型,防止修改所有数组类型变量的原型方法
let arrayProto = Array.prototype;// 数组原型上的方法
let proto = Object.create(arrayProto);
//重写以下几个方法
['splice','unshift','push','sort','reserve','shift','pop'].forEach(method=>{
    proto[method] = function(...args){
        let inserted;//默认没有插入新数据
        switch(method){
            case 'push':
            case 'unshift':
                inserted = args;//参数是数组
                break;
            case 'splice':
                inserted = args.slice(2);//splice方法参数大于等于三个才是添加
            default:
                break;
        }
        observeArray(inserted);
        console.log('视图更新');
        // Array.prototype.push.call([1,2,3],4,5,6);
        arrayProto[method].call(this,...args);
    }
});
//监控数组
function observeArray (obj){
    for(let i = 0; i<obj.length;i++){
            observe(obj[i])//数组中普通值不会被监控,对象会被监控
        }
}
//监控
function observe (obj){
    //基本数据类型直接返回不需要监控
    if((typeof obj !== 'object'&& typeof obj !== 'function') || obj == null){
        return obj
    }
    //数组的处理方式
    if(Array.isArray(obj)){
        //重写该数组原型的方法
        Object.setPrototypeOf(obj,proto);
        observeArray(obj);
    }else{//对象的处理方式
        for(let key in obj){
            defineReactive(obj,key,obj[key])
        }
    }
}
//调用Object.defineProperty()方法,监控数据
function defineReactive(obj,key,value){
    observe(value);//递归监控数据
    Object.defineProperty(obj,key,{
        get(){
            return value;
        },
        set(newValue){
            if(value!==newValue){
                observe(newValue);
                value = newValue;
            }
        }
    })
}
let data = {
    name:'yh',
    arr:[1,2,3]
}
observe(data);
data.arr = [1,2];//更新
data.arr.push(996);//更新
data.arr[3] = 251;//不更新

逻辑步骤:
1、传参data,判断data类型
2.1、如果是基本类型就直接返回
2.2、如果是数组则重写数组的那七个方法并循环数组将遍历的孩子作为data再次走第一步
2.3、如果是对象或函数,则给其循环添加监控,并将孩子作为data再次走第一步

特点: 使用对象的时候 必须先声明属性 ,这个属性才是响应式的
1.增加不存在的属性 不能更新视图 (vm.$set)
2.默认会递归增加 getter和setter
3.数组里套对象 对象是支持响应式变化的,如果是常量则没有效果
4.修改数组索引和长度 是不会导致视图更新的
5.如果新增的数据 vue中也会帮你监控(对象类型)

猜你喜欢

转载自www.cnblogs.com/yhbh/p/11995874.html