Vue渲染原理及其双向数据绑定详解
来源:互联网 发布:网易企业邮箱域名格式 编辑:程序博客网 时间:2024/04/25 15:53
双向数据绑定原理
1. 新建vue实例
var data = { text:'hello world!' }; var vm = new Vue({ el:'#app', data });
2. 将vue实例中的el HTML模板渲染进DOM
function nodeToFragment(node,vm) { var frag = document.createDocumentFragment(),//创建DocumentFragment片段 child; while(child = node.firstChild){//依次取node的子节点将其添加到frag中, compile(child,vm);//添加到DOM之前需对child和Vue实例进行绑定以监听彼此的变化 frag.appendChild(child);//此方法会同时删除node中的child节点 } return frag; } var dom = nodeToFragment(document.getElementById(id),this);document.getElementById(id).appendChild(dom);//将上面返回的节点添加进DOM
3. 将vue实例中的el HTML模板渲染进DOM,compile详解
function compile(node,vm) {//node为el的子节点 var reg = /\{\{(.*)\}\}/,// .为匹配除\r\n之外的任意单个字符,*为匹配前面字符任意多次 name; //元素节点 if(node.nodeType == 1){ var attr = node.attributes; for(var i = 0; i<attr.length; i++){//遍历el的子节点的属性,若其有v-model属性,变从vm.data中取v-model属性对应的值value,将value作为el的子节点的value|innerHTML值,因为v-model一般对应input元素 if(attr[i].nodeName == 'v-model'){ VModelEle.push(node); name = attr[i].nodeValue; node.value = vm.data[name]; node.innerHTML= vm.data[name]; node.addEventListener('input',function (e) { vm.data[name] = e.target.value; });//此处已假定node为input元素,监听此input,若其value有变化则将其反映到vm.data的name中,name为'v-model'属性对应的nodeValue。到这里,已经实现了DOM到vm.data的绑定。 new Watcher(vm,node,name);//这一步实现vm.data到DOM的绑定 node.removeAttribute('v-model');//从node中删除v-model属性。 break; } } } //若node为文本节点,判断文本节点的值是不是{{}}这种形式。 if(node.nodeType == 3){ if(reg.test(node.nodeValue)){ name = RegExp.$1;//RegExp为全局对象,$1-$9为最新匹配到的9个正则表达式中带括号的项,只能存储最新9个 name = name.trim();//取reg = /\{\{(.*)\}\}/中括号内匹配到的值,name在vm.data中也有 new Watcher(vm,node,name);//为vm.name添加监听器,实现从vm到DOM的绑定 } } }
4. 为vm.name添加监听器,new Watcher(vm,node,name)
- Dep方法详情
function Dep() { this.subs = []; } Dep.prototype = { addSub:function (sub) { this.subs.push(sub);//sub为Watcher实例 }, notify:function () { this.subs.forEach(function (sub) { sub.update();//通知所有Watcher更新DOM }) } };
- Watcher方法详情
function Watcher(vm,node,name) { Dep.target = this; this.name = name; this.node = node; this.vm = vm; this.update();//每次new Watcher时都要用vm.data[this.name]数据更新this.node.nodeValue,即实现vm.data到DOM的绑定。 Dep.target = null; } Watcher.prototype = { update:function () { this.node.nodeValue = this.vm.data[this.name]; } };
- 为
vm.data
中的每个数据重写其Object.defineProperty
中的set
和get
方法
function observe(obj) { Object.keys(obj).forEach(function (key) { defineReactive(obj,key,obj[key]); }) } function defineReactive(obj,key,val){//defineReactive即为每个data属性添加setter和getter,当在外部重新为data添加新属性时,还会调用此方法,接口为Vue.$set(obj,kay,value);。 var dep = new Dep(); Object.defineProperty(obj,key,{ //因为读取vm.data的地方比较多,比如compile方法中的node.value =vm.data[name];node.innerHTML= vm.data[name];而只有第一次为vm.data[name]添加Watcher时才需将此Watcher添加进Dep的subs中,因为new Watcher会执行Watcher的update方法,其中会读取this.vm.data[this.name]。 get:function () { if(Dep.target){ dep.addSub(Dep.target); } return val; }, //当重写vm.data中的属性时,就重置vModelEles中元素的value,vModelEles为所有有v-model属性的元素 set:function (value) { for(var ele in vModelEles){ vModelEles[ele].value = value; } if(value == val) return; //若两次值不同,将调用dep.notify方法,启动所有Watcher,更改nodeValue val = value; dep.notify(); console.log(val); } }); }
双向数据绑定原理总结
- 从DOM到vm.data很简单,即addEventListener监听DOM的变化,将其值写到vm.data中即可。
- 从vm.data到DOM:
- 为出现在DOM中的vm.data中的每个元素添加Watcher,所有的Watcher都存放在Dep的subs中
- 每当vm.data有变化就调用Dep的notify方法,即取出所有subs中的Watcher,调用Watcher的updata方法,更新DOM
阅读全文
0 0
- Vue渲染原理及其双向数据绑定详解
- vue双向数据绑定原理
- Vue 双向数据绑定原理
- Vue双向数据绑定原理分析
- vue双向数据绑定的原理解密
- vue双向数据绑定的原理
- Vue.js双向数据绑定原理
- vue实现数据双向绑定原理剖析
- Vue双向数据绑定原理解析
- vue.js双向数据绑定实现原理
- vue 列表渲染双向绑定
- vue双向绑定原理
- vue开发:vue,angular,react数据双向绑定原理分析
- Vue--数据双向绑定
- Vue双向数据绑定
- vue双向数据绑定原理探究(附demo)
- Vue实现双向绑定的原理以及响应式数据
- 【学习笔记】Vue中实现双向数据绑定的原理
- fitnesse学习历程1
- Compiling DCMTK for Android(中文版)
- 二叉树的一些基本知识总结
- c++builder字符串转换为日期的通用函数
- PAT练习-D进制A+B
- Vue渲染原理及其双向数据绑定详解
- CListBox的基本使用
- c++builder通过指定的分隔符格式化一个日期字符串
- 哈希查找
- ccf-201312-1
- 516. Longest Palindromic Subsequence
- ETL调优的一些分享
- Hibernate相关内容
- Gilde原码解析