模擬Vue雙向數(shù)據(jù)綁定

html部分:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>模擬vue雙向綁定</title>
</head>
<body>
  <div id="root">
    <ul>
      <li>123</li>
      <li>456</li>
      <li>789</li>
    </ul>
    <p>{{nickname}}</p>
    <p>{{age}}</p>
  </div>
</body>
</html>

js部分:

class MyVue{
    static sign = /\{\{(.+?)\}\}/g;     //  {{ }}正則匹配
    constructor(options){
      const _this = this;
      // _ 標識內(nèi)部屬性  , $表示 只讀私有屬性
      this._el = options.el;
      this._data = options.data;

      // 監(jiān)聽數(shù)據(jù)的變化
      for(let i in this._data){
        let d = _this[i] = this._data[i] //將this._data的數(shù)據(jù)綁定到MyVue實例中
        Object.defineProperty(_this,i,{
          get(){
            return d
          },
          set(newValue){
            console.log(newValue)
            d = newValue;
            _this.render()
          }
        })
      }
      this._templateDOM = document.getElementById(this._el)
      this._parent = this._templateDOM.parentNode;
      this.render()
      options.mounted.bind(_this)()
    }
    // 渲染
    render(){
      // 1.獲取每個dom及其子節(jié)點,正則匹配到每個節(jié)點
      let copyTemplate = this._templateDOM.cloneNode(true);   //深拷貝dom,含子節(jié)點
      this.compile(copyTemplate)
      this.update(copyTemplate)
    }

    // 編譯
    compile( template ){
      let _this = this;
      let childNodes = template.childNodes;
      for(let i = 0;i<childNodes.length;i++){
        let type = childNodes[i].nodeType;
        if(type === 3){
          // 文本節(jié)點
          let txt = childNodes[i].nodeValue;
          txt = txt.replace(MyVue.sign,function(_,group){
            //js中的replace函數(shù) 是支持回調(diào)函數(shù)的,回調(diào)中的第一個參數(shù)是匹配到的參數(shù),return可以返回一個希望匹配替換成的值
            let key = group.trim()
            let value = _this[key]
            return value;
          })
          childNodes[i].nodeValue = txt;
        }else if(type === 1){
          // node節(jié)點 遞歸調(diào)用
          _this.compile(childNodes[i])
        }
      }
    }
    // 更新替換
    update(realDom){
      let replacdChild = document.getElementById(this._el);
      this._parent.replaceChild(realDom,replacdChild)
    }
  }

  let VueDom = new MyVue({
    el:'root',
    data:{
      nickname:'我的名字',
      age:20
    },
    mounted(){
      setTimeout(() => {
        console.log('mounted',this)
        this.nickname = '你的你的'
      }, 2000);
    }
  })
  console.log(VueDom)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容