vue中对象的响应式原理

2021-7-26号笔记-Vue数据响应式原理

对象的响应式原理

1、 侦听数据

2、 收集依赖

3、 更新数据

过程:

1、在类Observer中,将vue中的data传入构造函数construstot中,进行保存

2、 判断是数组还是对象,如果是对象,就调用walk方法,遍历对象中的key与value,并且传入defineReactive()方法中。将这些数据变成响应式数据,进行劫持数据。

3、 defineReactive() 这个方法,首先会对上面遍历出来的val进行判断,如果还是对象,那么在new一个Observer,将该对象传入。之后new Dep出来用来收集依赖,之后调用object.defineProperty方法,里面有get和set方法,get用来收集依赖,将调用dep里面的addSub来收集依赖,而set方法,则会调用dep上的notify方法,而notify方法,会对所有的依赖队列里的依赖进行遍历,并且会对遍历出来的依赖进行调用watcher上面的update方法,进行数据更新。

export default class Observer {
	// 首先在constructor中对vue中的data进行保存、
	constructor (data) {
		this.value = data
	// 判断是数组还是对象
		if (Array.isArray(this.value)) {
			// 劫持数组,我们暂且放这。
		} else {
			// 如果时对象,那么就调用walk方法
			this.walk(this.value) // vue内部用来递归劫持数据的方法
		}
	}

	walk (obj) {
		const keys = Object.keys(obj)
		for (let i = 0; i < keys.length; i++) {
		// 遍历对象中的值,调用defineReactive方法,将对象里面的值,变为响应式的值
			defineReactive(obj, keys[i], obj[keys[i]])
		}
	}
}

function defineReactive(data, key, val) {
	// 新增判断当前属性值是否是对象,如果是对象,继续递归劫持
	if (typeof val === 'object') {
		new Obsever(val)
	}
	let dep = new Dep()
	Object.defineProperty(data, key, function() {
		enumerable: true, // 该属性是否可被枚举
		configurable: true, // 该属性的配置后续是否可进行更改
		get: function () { // 用于获取属性值
			// 收集依赖
			if (window.target) {
			// 调用dep上的addSub方法 将target添加到依赖队列上
				dep.addSub(window.target)
			}
			return val
		},
		set: function (newVal) { // 设置属性值
			if (newVal === val) return
			// 用新值替换旧值
			val = newVal
			// 数据发生变化时,通知依赖者
			dep.notify()
		}
	})
}

export default class Dep () {
	constructor() {
		this.sub = [] // 依赖者数组,用来存放依赖者watcher实例
	}

	addSub (sub) { // 添加依赖
		this.sub.push(sub)
	}

	remove (sub) { // 删除依赖
		remove(this.sub, sub)
	}

	// 通知方法,用于通知各个依赖者进行数据更新
	notify () {
		const arr = this.subs.slice() // 先拷贝一份
		for (let i = 0; i < arr.length; i++) {
			arr[i].update() // 让每一个watcher去调用自己的更新函数
		}
	}
}

export function remove (subs, sub) {
	if (subs.length && subs.length > 0) {
		const index = subs.indexOf(sub)
		if (index > -1) {
			return subs.splice(index, 1)
		}
	}
}


数组则是vue通过重新定义了一个array拦截器,让__proto__指向这个新的拦截器,进行拦截.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值