jsデータ双方向バインドの実現


前の記事「js実装データ一方向バインド」に続き、前の記事では原生jsでデータの一方向バインドが実現された.この記事では、jsでデータの双方向バインドを実現する方法について説明します.バインド方式はvueのv-model命令を模倣する.
ラベルの作成

:{{name}}

変数nameをv-modelプロパティでバインドする入力ボックスを作成します.ここではvueバインドの形式を模倣しているだけで、コードにはvue依存は導入されていません.完全に原生jsによって実現される.
ワンウェイバインド
let el = document.getElementById('app');
let template = el.innerHTML;
let _data = {
  name: '_BuzzLy'
};

let data = new Proxy(_data, {
  set(obj, name, value) {
    obj[name] = value;
    render();
  }
});

render();

function render() {
  el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
    str = str.substring(2, str.length - 2);
    return _data[str];
  });
}

ここで私たちはまた一方向バインドを実現しました.データの双方向バインドを実現するには簡単です.render関数を少し修正するだけです.
双方向バインド
function render() {
  el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
    str = str.substring(2, str.length - 2);
    return _data[str];
  });

  //     input  
  Array.from(el.getElementsByTagName('input'))
   //         v-model      
   .filter(ele => ele.getAttribute('v-model'))
   //     input  
   .forEach(input => {
      //    v-model    key,      key   value  input
      //          =>     
      let name = input.getAttribute('v-model');
      input.value = _data[name];
    
      //  input      
      input.oninput = function () {
        //  input   ,             data  
        //          =>     
        data[name] = this.value;
      };
  });
}

変更されたrender関数は、v-modelプロパティを持つinputラベルをフィルタリング、遍歴して取得し、データをビューにバインドし、ビューの変更によってデータの更新がトリガーされ、データの双方向バインドが実現されます.複雑に見えるバインドメカニズムは、私たちがよく知っているjsのいくつかの基礎的な操作によって実現されています.
完全なコード




  
  



  <div id="div1">
    <input type="text" v-model="name"/>
    <br/>   :{{name}}
  </div>

<script>
  let el = document.getElementById('div1');
  let template = el.innerHTML;
  let _data = {
    name: '_BuzzLy'
  };

  let data = new Proxy(_data, {
    set(obj, name, value) {
      obj[name] = value;
      render();
    }
  });

  render();

  function render() {
    el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
      str = str.substring(2, str.length - 2);
      return _data[str];
    });

    Array.from(el.getElementsByTagName('input'))
     .filter(ele => ele.getAttribute('v-model'))
     .forEach(input => {
       let name = input.getAttribute('v-model');
       input.value = _data[name];

       input.oninput = function () {
         data[name] = this.value;
       };
    });
  }
</script>

</code></pre> 
</article>
                            </div>
                        </div>