vue --- > 2.0数据的响应式的一种实现

初识:

  • 实际上是通过Object.defineProperty()方法来实现的
  • talk is cheap, show your code
let obj = {};
Object.defineProperty(obj, 'name', {
	get(){
		return document.querySelector('#name').innerHTML;
	},
	set(newVal){
		document.querySelector('#name').innerHTML = val;
	}
})

// 注1: 以上代码,将dom中id为name的值与obj.name属性绑定.
// 注2: 当在js文件中调用obj.name时,会触发obj的get函数(返回html内容)
// 注3: 当调用obj.name = xxx 时,会调用 obj 的set方法 

封装:

  • 知道了基本原理后,下一步是要将其封装起来!
// 首先创建一个Lz类.
class Lz{
	constructor(options){
		// 将传入的数据保存
		this.$options = options;

		// 数据响应化
		this.$data = options.data;
		this.observe(this.$data);
	}
	// 说明:
	// 将数据保存到this.$data中
	// observe函数用于给每一个数据添加set和get方法
	observe(value){
		if(!value || typeof value !== 'object'){
			return;
		}
			
		// 遍历该对象
		Object.keys(value).forEach(key =>{
			this.defineReactive(value, key, value[key])
		})
	}
	
	// 给数据添加响应式
	defineReactive(obj, key, val){
		Object.defineProperty(obj, key,{
			get(){
				return val
			},
			set(newVal){
				if(val === newVal) return;
				// 处理更新事件,此处使用console.log实现
				console.log(`数据更新辣: ${val} --- > ${newVal}`);
				val = newVal;
			}
		})
	}
}

引用Lz类

  • 在html中通过script标签导入Lz类
<body>
	<div id="app"></div>
	<script src="./lz.js"></script>
	<script>
		const app = new Lz({
			el:'#app',
			data:{
				foo:'bar',
				hello:{
					world:'您好,世界'
				}
			}
		})
	</script>
</body>
  • 打开浏览器,在控制台输入app.$data.foo
  • 尝试改变app.$data.foo的值
  • 尝试改变app.$data.hello.world的值
    在这里插入图片描述

浅拷贝

  • 以上,对第一个属性foo的操作成功的触发了set函数.
  • 由于浅拷贝复制的是引用,我们对对象的修改无法触发set.
  • 简单的理解就是set只负责监听自己这一层的变化,下一层的变化.不予监听
  • 解决办法,使用递归.给每一层添加一个setter方法.代码如下
  • 只需在defineReactive里面对world对象设置set和get
  • 重写defineReactive方法
defineReactive(obj, key, val){
	// 解决浅拷贝问题
	this.observe(val);
		
	Object.defineProperty(obj, key, {
		get(){
			return val;
		},
		set(newVal){
			if(newVal === val){
				return;
			}
			console.log(`${key}属性更新: ${val} --- > ${newVal}`);
			val = newVal;
		}
	})
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值