JavaScript响应式数据的实现(object)

原理:通过ES5中的Object.defineProperty方法实现,监听数据改变时的set方法,触发更新操作;

let info = {
	name: 'tomhe',
	age: 22,
}

function updated() {
	console.log('updated')
}

// 定义响应式数据方法
function defineReactive(target, key, value) {
	Object.defineProperty(target, key, {
		get() {
			return value
		},
		set(newValue) {
			updated()
			value = newValue
		},
	})
}

function observer(obj) {
	for (let key in obj) {
		defineReactive(obj, key, obj[key])
	}
}

observer(info)

info.name = 'tom'
console.log(info.name)

缺点:当出现嵌套的对象时,无法监听到深层数据的改变,如:{ name: { firstname: 'tom', lastname: 'he' } },当name中的属性firstname或lastname发生变化时,是不会触发updated方法的;同理当给当前属性赋值一个新对象后,改变新赋值的属性值,也是监听不到数据的变化的;可以通过判断属性值是否为对象进行递归监听;

改进后的方案如下:

let info = {
	age: 22,
	name: {
		firstname: 'tom',
		lastname: 'he',
	},
}

function updated() {
	console.log('updated')
}

// 判断值是否为对象
function isObject(val) {
	return val.constructor === Object
}

// 定义响应式数据方法
function defineReactive(target, key, value) {
	// 嵌套对象判断
	observer(value)
	Object.defineProperty(target, key, {
		get() {
			return value
		},
		set(newValue) {
			// 新增值为对象判断
			if (isObject(newValue)) {
				observer(newValue)
			}
			updated()
			value = newValue
		},
	})
}

function observer(obj) {
	if (!isObject(obj)) return
	for (let key in obj) {
		defineReactive(obj, key, obj[key])
	}
}

observer(info)

info.name.firstname = 'tom'
info.name.lastname = 'he'

参考链接:https://www.codenong.com/j5dc4060ef265da4d560/

你可能感兴趣的:(JavaScript,javascript,前端,开发语言)