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中也会帮你监控(对象类型)

posted @ 2019-12-06 16:08  娜辉  阅读(406)  评论(0编辑  收藏  举报