注意
避免自调用陷入死循环
Object.defineProperty(data, key, {
get() {
return data[key]
},
set(v) {
data[key] = v
}
})
监听data
中的key
,在get
中使用data[key]
相当于又调用一遍get
,解决方法:可以使用中转变量接受源数据
代码
interface options {
data: object
}
class Reactive {
_data: object
constructor(options: options) {
this._data = this.addReactive(options.data)
// 为实例添加响应式
for (const key in this._data) {
if (!Object.prototype.hasOwnProperty.call(this, key)) {
this[key] = this._data[key]
// 将根数据的响应式添加到实例身上
Object.defineProperty(this, key, {
get() {
// get has called
console.log(`get ${key}`)
return this._data[key]
},
set(v) {
// set has called
console.log(`set ${key}`)
this._data[key] = v
}
})
}
}
}
/**
* @method 为数据添加响应式
* @param {object} source 源数据
* @return {object} 响应式数据
*/
addReactive(source: object) {
var res = { ...source }
for (const key in res) {
// 给每一个属性添加数据劫持
Object.defineProperty(res, key, {
get() {
// get has called
return source[key]
},
set(v) {
// set has called
source[key] = v
}
})
// 如果当前属性为object类型则递归调用添加数据劫持
if (typeof res[key] === "object") {
res[key] = this.addReactive(res[key])
}
}
return res
}
}
var tes = new Reactive({
data: {
a: "1",
b: 23,
c: "hello world",
d: {
test: "aaa",
text: "bbb"
}
}
})
console.log(tes)