Commit 23: solved the setter init invoke
主要改动:在绑定指令之后就初始化值
备注:之前是节点都处理完毕之后,对scope中的值赋值(参见
src/seed.js
中的Seed函数),现在是在一个指令绑定完后就初始化(参见src/seed.js
中的_bind函数)
Commit 24: better unbind/destroy
- 主要改动:改进了unbind和destroy
- 增加了原型方法
Seed.prototype.destroy
-
each
指令增加了unbind
方法
- 增加了原型方法
Commit 25: fix sd-on
略
Commit 26: computed property progress
-
主要改动:支持计算属性
Directive.prototype.update = function (value) { // computed property if (typeof value === 'function' && !this.fn) { value = value() } // ... }
Commit 27: event delegation in sd-each
主要改动:对有
sd-each
的节点的事件委托给父节点-
原理
-
之前的逻辑是,对于以下代码,最后生成的每个
li
都绑定了事件<ul sd-show="todos"> <li class="todo" sd-each="todo:todos" sd-class="done:todo.done">...</li> </ul>
优化之后,对于
sd-each
的情况,采用事件委托的方式来处理。思路:在处理
sd-on
属性时增加sd-each
的情况-
on
指令的结构-
bind
:指令第一次绑定到元素时调用在
Seed.prototype._bind
函数中,我们可以发现一系列绑定操作后调用了指令的bind
方法 -
update
:值更新时调用在
Seed.prototype._createBinding
函数中,我们可以发现set
的时候会调用指令的update
方法 unbind
:移除监听器
-
-
on
指令处理过程-
bind
在正常进行绑定后,先调用
bind
方法bind: function (handler) { // each的情况 if (this.seed.each) { this.selector = '[' + this.directiveName + '*="' + this.expression + '"]' // 委托给父节点 this.delegator = this.seed.el.parentNode } }
-
update
update: function (handler) { // 移除监听器 this.unbind() if (!handler) return var self = this, event = this.arg, selector = this.selector, delegator = this.delegator if (delegator) { // 需要进行事件委托的节点 // for each blocks, delegate for better performance if (!delegator[selector]) { console.log('binding listener') delegator[selector] = function (e) { // 触发事件的对象 var target = delegateCheck(e.target, delegator, selector) if (target) { handler({ el : target, originalEvent : e, directive : self, seed : target.seed }) } } // 在delegator(父节点)上添加监听器 delegator.addEventListener(event, delegator[selector]) } } else { // 普通处理 // a normal handler this.handler = function (e) { handler({ el : e.currentTarget, originalEvent : e, directive : self, seed : self.seed }) } this.el.addEventListener(event, this.handler) } }
-
-
Commit 28: break directives into individual files
把directives
中的指令拆成单独的文件了
Commit 29: arrayWatcher
主要改动:改进了数组监听
-
原理
之前的实现:(Commit 10: kinda working now.)
-
改进之后:
- 仍然是沿袭了之前的思想,即在数组中增加了
pop
、push
等与Array.prototype
中同名的方法。在这些方法中进行了相关扩展 - 改进的是回调函数,即数组变化后(实际上是调用了
pop
、push
等函数后)应该执行的动作
- 仍然是沿袭了之前的思想,即在数组中增加了
-
代码实现
-
watchArray
函数该函数的作用是给
arr
增加push/pop/shift/unshift/splice/sort/reverse
方法。以
push
为例,arr[push]
函数的作用是:第一步,调用
Array.prototype
中的原生push
方法,得到一个新数组result
;第二步,执行回调函数。回调函数的参数是 方法名(
push
)、原数组的拷贝、result
function watchArray (arr, callback) { Object.keys(mutationHandlers).forEach(function (method) { arr[method] = function () { // 调用Array.prototype中的原生push方法 var result = Array.prototype[method].apply(this, arguments) // 执行回调函数 callback({ method: method, args: Array.prototype.slice.call(arguments), result: result }) } }) }
-
利用
watchArray
监控数组的变化以上我们知道,
watchArray
函数可以在数组调用push/pop/shift/unshift/splice/sort/reverse
方法时,执行一个回调函数。因此,我们就可以做到每次在数组发生变化时,及时更新DOM在
mutationHandlers
中就记录了每个方法执行后该进行哪些后续操作watchArray(collection, function (mutation) { // 调用mutationHandlers中的对应方法 mutationHandlers[mutation.method].call(self, mutation) })
-
Commit 30: allow overwritting mutationHandlers
支持重写mutationHandlers