以下内容还在研究中,描述可能不完全准确,仅供参考

  • 为每一处需要动态更新的DOM节点,创建一个属性对象

    1
    2
    3
    4
    5
    6
    var attrs = map.call(node.attributes, function (attr) {
    return {
    name: attr.name,
    expressions: attr.value.split(',')
    }
    })
  • 根据attr对象,分析绑定关系

    1
    2
    3
    4
    5
    attrs.forEach(function (attr) {
    attr.expressions.forEach(function (exp) {
    var binding = bindingParser.parse(attr.name, exp)
    })
    })
  • 解析属性对象,从指令函数库中,取出对应指令函数
    指令函数存在,创建binding对象

    1
    2
    3
    4
    5
    6
    7
    parse: function (dirname, expression) {
    var dir = directives[dirname]

    return dir && valid
    ? new Binding(dirname, expression)
    : null
    }
  • 解析指令,存储在binding对象上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    function Binding(directiveName, expression) {
    var directive = directives[directiveName]
    if (typeof directive === 'function') {
    this._update = directive
    } else {
    for (var prop in directive) {
    if (prop === 'update') {
    this['_update'] = directive.update
    } else {
    this[prop] = directive[prop]
    }
    }
    }
    }

    //
    this.key = argMatch
    ? argMatch[2].trim()
    : rawKey.trim()

    this.arg = argMatch
    ? argMatch[1].trim()
    : null

    //
    this.filters = filterExpressions.map(function (filter) {
    var tokens = filter.slice(1)
    .match(FILTER_TOKEN_RE)
    .map(function (token) {
    return token.replace(QUOTE_RE, '').trim()
    })
    return {
    name: tokens[0],
    apply: filters[tokens[0]],
    args: tokens.length > 1
    ? tokens.slice(1)
    : null
    }
    })

    //
    Seed.prototype._compileNode = function (node, root) {
    var self = this
    self._bind(node, binding)
    }
    Seed.prototype._bind = function (node, bindingInstance) {
    bindingInstance.seed = this
    bindingInstance.el = node
    }
  • 子节点遍历解析

    1
    2
    3
    4
    5
    if (node.childNodes.length) {
    each.call(node.childNodes, function (child) {
    self._compileNode(child)
    })
    }
  • 指令对象观测的数据变化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    Seed.prototype._bind = function (node, bindingInstance) {
    var binding = seed._bindings[key] || seed._createBinding(key)
    binding.instances.push(bindingInstance)
    if (bindingInstance.bind) {
    bindingInstance.bind(binding.value)
    }
    }

    Seed.prototype._createBinding = function (key) {

    var binding = {
    value: null,
    instances: []
    }

    this._bindings[key] = binding

    // bind accessor triggers to scope
    Object.defineProperty(this.scope, key, {
    get: function () {
    return binding.value
    },
    set: function (value) {
    binding.value = value
    binding.instances.forEach(function (instance) {
    instance.update(value)
    })
    }
    })

    return binding
    }
  • 解析完root节点,继续解析子节点

    1
    2
    3
    4
    5
    6
    7
    8
    Seed.prototype._compileNode = function (node, root) {
    var self = this
    if (node.childNodes.length) {
    each.call(node.childNodes, function (child) {
    self._compileNode(child)
    })
    }
    }
  • 初始化变量,触发setters

    1
    2
    3
    4
    5
    function Seed(el, data, options) {
    for (key in dataCopy) {
    this.scope[key] = dataCopy[key]
    }
    }