模仿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
相關文章
相關標籤/搜索