Imitate vue data hijacking, achieve mvvm

The imitation vue mvvm implementations, data rendering, and v-model data changes
the source address

  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>
复制代码

To achieve data replacement function

  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 {
        
      }
    })
  }
}
复制代码

Open your browser mvvm mode has been achieved, there is a problem

{{message}}

Has not been replaced, but also requires the use of nested recursive search and replace

  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, we can achieve far multilayer nested data

Next realization 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;
      });
  }
})
复制代码

Next
to realize simple simple vuex

Reproduced in: https: //juejin.im/post/5cf79260518825399965a582

Guess you like

Origin blog.csdn.net/weixin_34288121/article/details/93171235