模仿vue的数据劫持,实现mvvm

模仿vue的mvvm实现方式,实现数据渲、改变data以及v-model
源码地址vue

script src="Tvue.js"></script>
  <body>
    <div id="app">
      {{message}}
      <p>{{message}}</p>
    </div>
  </body>
  <script>
    let vm = new Tvue({
      el: "#app",
      data: {
        message: '测试'
      }
    })
  </script>
复制代码

先实现数据替换功能node

class Tvue {
  constructor(options) {  // new Tvue里的值
    this.$options = options
    this._data = options.data  // 参考源码,避免与data重名
    this.compile(options.el)  // 查找替换
  }
  compile(el) {
    //  做用域 范围内查找   
    let element = document.querySelector(el)  // 获取<div id="app"></div>
    let childNodes = element.childNodes  // 获取子节点
    Array.from(childNodes).forEach((node) => {
      // console.log(node, 'nodeType 属性可用来区分不一样类型的节点,好比 元素, 文本 和 注释。')
      if (node.nodeType === 3) {
        // 文本替换
        let nodeContent = node.textContent
        let reg = /\{\{\s*(\S*)\s*\}\}/  // 考虑插值表达式的先后空格
        if (reg.test(nodeContent)) {  
          node.textContent = this._data[RegExp.$1]
        }
      } else {
        
      }
    })
  }
}
复制代码

打开浏览器mvvm模式已经实现,有个问题是git

{{message}}github

尚未被替换,还须要使用递归实现多层嵌套查找替换

compileNode(element) { // 递归实现多层嵌套查找替换
    let childNodes = element.childNodes // 获取子节点
    Array.from(childNodes).forEach((node) => {
      // console.log(node, 'nodeType 属性可用来区分不一样类型的节点,好比 元素, 文本 和 注释。')
      if (node.nodeType === 3) {
        // 文本替换
        let nodeContent = node.textContent
        let reg = /\{\{\s*(\S*)\s*\}\}/ // 考虑插值表达式的先后空格
        if (reg.test(nodeContent)) {
          node.textContent = this._data[RegExp.$1]
        }
      } else if (node.nodeType === 1) {  // 处理标签

      }
      if (node.childNodes.length > 0) {
        this.compileNode(node)
      }
    })
  }
复制代码

OK,截止目前能够实现多层数据嵌套vuex

接下来实现v-model

let attrs = node.attributes;
Array.from(attrs).forEach(attr => {
  let attrName = attr.name;
  let attrValue = attr.value;
  if (attrName.indexOf("t-") == 0) {
      attrName = attrName.substr(2);
      if (attrName == "model") {
          node.value = this._data[attrValue];
      }
      node.addEventListener("input", e => {
          this._data[attrValue] = e.target.value;
      })
      new Watcher(this, attrValue, newValue => {
          node.value = newValue;
      });
  }
})
复制代码

下一篇
实现简约不简单的vuex
相关文章
相关标签/搜索