vue.js双向数据绑定实现原理

来源:互联网 发布:日本马油怎么样知乎 编辑:程序博客网 时间:2024/04/26 03:11

源码如下:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>   <div id="app">     <input type="text" v-model="text">     {{text}}   </div>   <script>  /*var dom = nodeToFragment(document.getElementById('app'));      console.log(dom);*/      function compile(node,vm) {        var reg =/\{\{(.*)\}\}/;        //节点类型为元素        if(node.nodeType === 1){          var attr = node.attributes;          //解析属性          for(var i=0;i<attr.length;i++){            if(attr[i].nodeName = 'v-model'){              var name = attr[i].nodeValue;//获取v-model绑定的属性名              //放在该位置原因是获取name值              node.addEventListener('input',function (e) {                //给相应的data属性赋值,进而触发该属性的set方法                vm[name]=e.target.value;              });              node.value = vm[name];              node.removeAttribute('v-model');            }          };        }        //节点类型为text        if(node.nodeType === 3){          if(reg.test(node.nodeValue)){            var name = RegExp.$1;//1.获取匹配到的字符串            name = name.trim();            //node.nodeValue = vm[name];//将data的值赋值给该node            new Watcher(vm,node,name);          }        }      }      function nodeToFragment(node,vm) {         var flag = document.createDocumentFragment();         var child;         while(child = node.firstChild){           compile(child,vm);           flag.append(child);         }        return flag;      }      function defineReactive(obj,key,val) {          var dep = new Dep();          Object.defineProperty(obj,key,{            get:function () {               if(Dep.target) dep.addSub(Dep.target);               return val;            },            set:function (newVal) {              if(newVal===val) return ;              val = newVal;              //console.log(val);              //作为发布者发出通知              dep.notify();            }          });      }      function observe(obj,vm) {        Object.keys(obj).forEach(function (key) {           defineReactive(vm,key,obj[key]);        })      }      function Vue(options) {         this.data = options.data;         var data = this.data;         observe(data,this);         var id = options.el;         var dom = nodeToFragment(document.getElementById(id),this);        //编译完成后,将dom返回到app中        document.getElementById('app').appendChild(dom);      }     function Dep() {        this.subs = [];     }     Dep.prototype={       addSub:function (sub) {         this.subs.push(sub);       },       notify:function () {         this.subs.forEach(function (sub) {           sub.update();         });       }     }     function Watcher(vm,node,name) {       Dep.target = this;       this.name = name;       this.node = node;       this.vm = vm;       this.update();       Dep.target=null;     }  Watcher.prototype={    update:function () {      this.get();      this.node.nodeValue = this.value;    },    //获取data中的属性值    get:function () {      this.value = this.vm[this.name];//触发相应属性的get    }  };     var vm = new Vue({       el:'app',       data:{         text:'hello world'       }     });   </script></body></html>

参考:http://www.jb51.net/article/99129.htm

原创粉丝点击