SOURCE

function Compiler (el, vm) {
  this.el = document.querySelector(el)
  this.vm = vm
  this.fragment = null
  this.init()
}

Compiler.prototype = {
  init: function () {
    if (this.el) {
      this.fragment = this.nodeToFragment(this.el)
      this.compileFragment(this.fragment)
      this.el.appendChild(this.fragment)
    } else {
      console.error('DOM节点不存在')
    }
  },
  // 将DOM节点转换成fragment
  nodeToFragment: function (el) {
    var fragment = document.createDocumentFragment()
		var child = el.childNodes
    
    while (child) {
      fragement.appendChild(child)
      child = el.childNodes
    }
    
    return fragment
  },
  // 解析模板
  compileFragment: function (el) {
		var childNodes = el.childNodes
    var self = this
    var reg = /\{\{(.*)\}\}/
    
    [].slice.call(childNodes).forEach(function (node) {
      var text = node.textContent
      
      // 当前节点是文本节点并且符合正则要求
      if (self.isTextNode(node) && reg.test(text)) {
        self.compileText(node, reg.exec(text)[1])
      }
      
      var _child = node.childNodes
      
      // 递归遍历子节点
      if (_child && _child.length) {
        self.compileFragment(node)
      }
    })
  },
  // 解析文本
  compileText: function (node, exp) {
    var self = this
    var initText = this.vm[exp]
    
    this.updateText(node, initText) // 将初始化数据更新到视图中
    new Watcher(this.vm, exp, function (value) { // 生成订阅器绑定更新函数
      self.updateText(node, value)
    })
  },
  updateText: function (node. value) {
    node.textContent = typeof value === 'undefined' ? '' : value
  },
  isTextNode: function (node) {
    return node.nodeType === 3
  }
}
console 命令行工具 X clear

                    
>
console