Commit 6 - 12:初步实现each

Commit 6: refactor

  • 主要改动:重构
  • 备注:逻辑的改动并不大,主要是结构上面重构了一下

Commit 7: augmentArray seems to work

  • 主要改动:开始添加sd-each

Commit 8: WIP

  • 主要改动:持续重构

Commit 9: refactor

  • 主要改动:添加了全局apiVue.extend

  • 以下是目前的代码结构

    Commit 6 - 12:初步实现each_第1张图片
    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的运行过程)

    Commit 6 - 12:初步实现each_第2张图片
    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
        }
    }
    
  • 总结

    1. 处理节点时采用递归的方式
    2. sd-each时,会给列表中的每个元素生成一个子实例

你可能感兴趣的:(Commit 6 - 12:初步实现each)