题目
深层次数据变化如何逐层往上传播?
let app2 = new Observer({ name: { firstName: 'shaofeng', lastName: 'liang' }, age: 25});app2.$watch('name', function (newName) { console.log('我的姓名发生了变化,可能是姓氏变了,也可能是名字变了。')});app2.data.name.firstName = 'hahaha';// 输出:我的姓名发生了变化,可能是姓氏变了,也可能是名字变了。app2.data.name.lastName = 'blablabla';// 输出:我的姓名发生了变化,可能是姓氏变了,也可能是名字变了。
观察到了吗?firstName 和 lastName 作为 name 的属性,其中任意一个发生变化,都会得出以下结论:"name 发生了变化。"这种机制符合”事件传播“机制,方向是从底层往上逐层传播到顶层。
这现象想必你们也见过,比如:“点击某一个DOM元素,相当于也其父元素和其所有祖先元素。”(当然,你可以手动禁止事件传播) 所以,这里的本质是:"浏览器内部实现了一个事件传播的机制",你有信心自己实现一个吗?
我的代码
function Observer(obj) { this.data = obj; // 对象挂载点 this.$p = Array.prototype.slice.call(arguments,1)[0] || 'data'; // 实现事件冒泡储存父级 名字 this.transformAll(obj); // 对obj对象进行 遍历, 然后调用convat 进行defineProperty改写}Observer.prototype.transformAll = function(obj) { var keyarr = Object.keys(obj); for (var i=0,len=keyarr.length;i
、、。
实现方式
在动态数据绑定(二)中需要实现一个事件系统,我的实现是在原型链上建立一个content
属性保存所有需要绑定的事件名称
和触发函数
.如下:
Observer.prototype.content = {}
事件系统应该是能监听所有的实例化对象绑定的函数,在判断改写和深度convat
当中都会创建一个新的实例化对象,如果写到this
上就无法通用了。
还有一个痛点是如何知道父级
对象的key
值,好在函数里面对基本类型和对象类型的区分十分明了,只要在检测到是对象类型的哪一条路上多传入一个参数,传入当前的属性的key
给下层,下层再利用这个key
就好了。
想要得到冒泡,触发事件的时候就一定要携带上父级的key
信息,我使用了
new Observer(value,this.$p + '.' + key);
set: function(newval){ var allkey = $p+ '.' + key; console.log('你设置了 '+ key + ', ' + '新的值为 ' + newval); self.emit(allkey, newval); // 触发形式为 father.child newval为传入信息 if (newval instanceof Object ) { new Observer(newval, allkey); // 如果改写为对象 } val = newval }
emit($p+ '.' + key, newval)
,触发的时候就变成了data.name.firstName
的形式,传入的$p
一定是保存着所有上层的key
值,接着再在emit
函数内部解析一下 ,触发data
、name
、firstName
即可。
有个问题,现在函数的执行顺序是由上到下了,明天写个setTimeout
,刚好可以加深理解js的任务循环机制?
写的很乱,脖子和腰都在抗议了,抽空从第一个任务写起来,今天先合电脑睡觉??