Commit 6 - 12:初步实现each
2018-12-21 本文已影响21人
丨ouo丨
Commit 6: refactor
- 主要改动:重构
- 备注:逻辑的改动并不大,主要是结构上面重构了一下
Commit 7: augmentArray seems to work
- 主要改动:开始添加
sd-each
Commit 8: WIP
- 主要改动:持续重构
Commit 9: refactor
-
主要改动:添加了全局api
Vue.extend
-
以下是目前的代码结构
Commit9-结构.png
Commit 10: kinda working now.
-
主要改动:监听array变化
-
代码实现:
-
src/directives.js,each部分
each: { update: function (collection) { watchArray(collection, this.mutate.bind(this)) }, mutate: function (mutation) { console.log(mutation) console.log(this) } }
-
src/watchArray.js
var proto = Array.prototype, slice = proto.slice, mutatorMethods = [ 'pop', 'push', 'reverse', 'shift', 'unshift', 'splice', 'sort' ] module.exports = function (arr, callback) { mutatorMethods.forEach(function (method) { arr[method] = function () { // 调用原生同名方法 proto[method].apply(this, arguments) // 回调 callback({ event: method, args: slice.call(arguments), array: arr }) } }) }
-
Commit 11: sd-each-* works
- 主要改动:实现了部分
sd-each
的逻辑 - 备注:运行了一下,buildItem函数会报错,但是在下一个提交已经修复了。
Commit 12: big refactor.. again
-
主要改动:一次比较大的重构,初步实现
sd-each
列表(可以生成li了) -
流程图(dev.html的运行过程)
Commit12.png在绑定完指令后,对变量进行赋值时,会调用指令中的update方法(绑定指令详见commit2)。因此,通过阅读
each
指令的代码,就可以知道列表的实现原理。each: { // 在第一次绑定完后调用 bind: function () { this.el['sd-block'] = true this.prefixRE = new RegExp('^' + this.arg + '.') var ctn = this.container = this.el.parentNode this.marker = document.createComment('sd-each-' + this.arg + '-marker') ctn.insertBefore(this.marker, this.el) ctn.removeChild(this.el) this.childSeeds = [] }, // set的时候调用 update: function (collection) { if (this.childSeeds.length) { this.childSeeds.forEach(function (child) { child.destroy() }) this.childSeeds = [] } // 见commit10 watchArray(collection, this.mutate.bind(this)) var self = this // 循环生成子实例 collection.forEach(function (item, i) { self.childSeeds.push(self.buildItem(item, i, collection)) }) }, // mutate: function (mutation) { console.log(mutation) }, // 生成子实例 buildItem: function (data, index, collection) { var Seed = require('./seed'), // 克隆一个节点node node = this.el.cloneNode(true), ctrl = node.getAttribute(config.prefix + '-controller'), Ctrl = ctrl ? controllers[ctrl] : Seed if (ctrl) node.removeAttribute(config.prefix + '-controller') // 以node、data生成子实例 var spore = new Ctrl(node, data, { eachPrefixRE: this.prefixRE, parentScope: this.seed.scope }) // 在页面中插入node this.container.insertBefore(node, this.marker) collection[index] = spore.scope return spore } }
-
总结
- 处理节点时采用递归的方式
- sd-each时,会给列表中的每个元素生成一个子实例