您的位置:首页 > Web前端 > JavaScript

JS 数据监听方法研究

2017-07-16 16:03 423 查看
之前模拟了一个在 HTML标签中通过自定义的 yjb-bind 和 yjb-model来进行数据绑定的,效果很不好。指令解析及数据绑定应该是在解析 DOM 树时做的,采用
getAttribute
querySelectorAll
等方式来获取绑定的信息和元素,性能非常差,并且难以通过 person.name 这类的字符串访问到对象内的属性(Vue 好像是自己实现了一个解析路径字符串访问对象内属性的方法)。

所以,这次我直接抛弃了上来就想什么都做了的幻想,只研究数据监听,解析 DOM和数据绑定留待之后再研究~

正题

假设 instance 是一个框架的实例,里面的 data 对象就是初始化实例时的数据,可以看到,data 中有基本类型的属性,也有对象和数组。

这里参考了 Vue,Vue 中初始化的数据是在实例的 data 属性内,而初始化后数据还会在实例中保存一份,目的是为了通过 setter 设置监听。因为 setter 是在为该属性赋值时触发的,替换了默认的赋值操作,因此无法再在内部对该属性赋值,因为这样会递归调用这个 setter,然后就堆栈溢出了~但是必须把这个新的值保存起来,不然咋读取呢对吧

var instance = {
data: {
a: 10,
b: 20,
obj: {
c: 30,
d: 40
},
arr: [10, 20, 30]
}
};


然后下面是设置数据监听的函数

/**
*
* @param saveData 实际保存的对象
* @param data 用户直接操作的对象
*/
function setObserver(saveData, data) {
//  获取对象的所有属性
Object.keys(data).forEach(function (key, index, arr) {
//  判断类型,如果是对象则递归调用这个函数
if(typeof data[key] === 'object') {
saveData[key] = {}
setObserver(saveData[key], data[key])
} else {
//  保存数据
saveData[key] = data[key]
//  设置监听操作和获取操作
Object.defineProperty(data, key, {
set (newVal) {
saveData[key] = newVal;
//  其他监听到数据修改后的操作,如:
update(saveData, key);
},
get () {
return saveData[key];
}
})
}
})
}

setObserver(instance._data = {}, instance.data)


//  瞎写的,为的是在监测到数据修改时提示一下
function update(data, key) {
console.log("数据更新啦~");
console.log(data);
}


用户进行操作的是 instance.data 中的属性,而实际保存到的是 instance._data 中的属性,通过 getter 获取 instance.data 中的属性时返回的也是 instance._data 中的属性。

可以把整段代码复制运行一下测试测试,可以看到,对 instance.data 对象内的所有属性的赋值操作,都会触发监听函数。包括对象内的属性,如
instance.data.obj.c = "cccccc"
等,并且,
instance.data.arr[1] = "Array~~~~"
这样对已有的数组元素赋值也是可以的,但是对对象或数组添加或删除元素,目前还是无法监测到的。

Vue 中,在 setter 方法内部,还会判断数据是否和之前的值相同,如果相同则直接 return,即不触发后续操作,减少不必要的性能浪费:

if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐