vue双向数据绑定原理探究(附demo)


Posted in Javascript onJanuary 17, 2017

昨天被导师叫去研究了一下vue的双向数据绑定原理。。。本来以为原理的东西都非常高深,没想到vue的双向绑定真的很好理解啊。。。自己动手写了一个。

传送门

双向绑定的思想

双向数据绑定的思想就是数据层与UI层的同步,数据再两者之间的任一者发生变化时都会同步更新到另一者。

双向绑定的一些方法

目前,前端实现数据双向数据绑定的方法大致有以下三种:

1.发布者-订阅者模式(backbone.js)

思路:使用自定义的data属性在HTML代码中指明绑定。所有绑定起来的JavaScript对象以及DOM元素都将“订阅”一个发布者对象。任何时候如果JavaScript对象或者一个HTML输入字段被侦测到发生了变化,我们将代理事件到发布者-订阅者模式,这会反过来将变化广播并传播到所有绑定的对象和元素。

2.赃值检测(angular.js)

思路:通过轮询的方式检测数据变动。才特定的事件触发时进入赃值检测。

大致如下:

•   DOM事件,譬如用户输入文本,点击按钮等。( ng-click )

•   XHR响应事件 ( $http )

•   浏览器Location变更事件 ( $location )

•   Timer事件( $timeout , $interval )

•   执行 $digest() 或 $apply()

3.数据劫持(vue.js)

思路:使用Object.defineProperty对数据对象做属性get和set的监听,当有数据读取和赋值操作时则调用节点的指令,这样使用最通用的=等号赋值就可以触发了。

wue双向数据绑定小demo思路

①  构造一个Wue对象,定义该对象的属性el、data,创建对象的时候传相应数据,并执行init()方法。

var Wue=function(params){
 this.el=document.querySelector(params.el);
 this.data=params.data;
 this.init();
};

②  Init方法中执行bindText和bindModel方法,这两个方法分别是解析dom中绑定了w-model、w-text指令的html,并作相应处理。

init:function(){
  this.bindText();
  this.bindModel();
 }

③  bindText方法,把带有w-text指令的元素放进一个数组中,如:w-text='demo',然后令其innerHTML的值等于传进来的data[demo]。

bindText:function(){
  var textDOMs=this.el.querySelectorAll('[w-text]'),
  bindText;
  for(var i=0;i<textDOMs.length;i++){
  bindText=textDOMs[i].getAttribute('w-text');
  textDOMs[i].innerHTML=this.data[bindText];
  }
 }

④  bindModel方法,把带有w-model指令的元素(一般为form相关元素)放进一个数组中,如:w-model='demo',为每一个元素绑定keyup事件(兼容浏览器写法)。

bindModel:function(){
 var modelDOMs=this.el.querySelectorAll('[w-model]'),
 bindModel;
 var _that=this;
 for(var i=0;i<modelDOMs.length;i++){
 bindModel=modelDOMs[i].getAttribute('w-model');
 modelDOMs[i].value=this.data[bindModel]||'';
 //数据劫持
 this.defineObj(this.data,bindModel);
 if(document.addEventListener){
 modelDOMs[i].addEventListener('keyup',function(event) {
  console.log('test');
  e=event||window.event;
  _that.data[bindModel]=e.target.value;
 },false);
 }else{
 modelDOMs[i].attachEvent('onkeyup',function(event){
  e=event||window.event;
  _that.data[bindModel]=e.target.value; 
 },false);
 }
 } 
}

⑤  使用Object.defineProperty,定义set和get方法,并在set方法中调用bindText方法。这是利用了一旦w-model的值在input中被改变,会自动执行set方法,所以只有在这个方法中调用更新w-text的方法即可。

defineObj:function(obj,prop,value){
  var val=value||'';
  var _that=this;
  try{
  Object.defineProperty(obj,prop,{
  get:function(){
  return val;
  },
  set:function(newVal){
  val=newVal;
  _that.bindText();
  }
  })
 
  }catch (err){
  console.log('Browser not support!')
  } 
 }

⑥使用

html:<br><h3>双向数据绑定demo</h3>
<div id="wrap">
 <input type="text" w-model='demo'>
 <h5 w-text='demo'></h5>
</div><br>js:
 <script src='../js/wue.js'></script>
 <script>
 new Wue({
 el:'#wrap',
 data:{
  demo:'winty'
 }
 })
 </script>

完整demo下载:https://github.com/LuckyWinty/two-way-data

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript基本对象
Jan 11 Javascript
javscript对象原型的一些看法
Sep 19 Javascript
ASP.NET jQuery 实例1(在TextBox里面创建一个默认提示)
Jan 13 Javascript
javascript瀑布流式图片懒加载实例解析与优化
Feb 23 Javascript
jQuery1.9+中删除了live以后的替代方法
Jun 17 Javascript
深入理解JavaScript中Ajax
Aug 02 Javascript
Vue.js bootstrap前端实现分页和排序
Mar 10 Javascript
AngularJS实现的省市二级联动功能示例【可对选项实现增删】
Oct 26 Javascript
9种改善AngularJS性能的方法
Nov 28 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
Jun 18 jQuery
vue element和nuxt的使用技巧分享
Jan 14 Vue.js
JS+CSS实现动态时钟
Feb 19 Javascript
JavaScript中英文字符长度统计方法示例【按照中文占2个字符】
Jan 17 #Javascript
浅析vue数据绑定
Jan 17 #Javascript
JavaScript使用正则表达式获取全部分组内容的方法示例
Jan 17 #Javascript
JavaScript使用delete删除数组元素用法示例【数组长度不变】
Jan 17 #Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
Jan 17 #Javascript
详谈JavaScript的闭包及应用
Jan 17 #Javascript
用原生js做单页应用
Jan 17 #Javascript
You might like
解析使用substr截取UTF-8中文字符串出现乱码的问题
2013/06/20 PHP
javascript编程起步(第六课)
2007/02/27 Javascript
几个javascript操作word的参考代码
2009/10/26 Javascript
为调试JavaScript添加输出窗口的代码
2010/02/07 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
一样的table?不一样的table(可编辑状态table)
2012/09/19 Javascript
利用js实现禁止复制文本信息
2015/06/03 Javascript
javascript动态生成树形菜单的方法
2015/11/14 Javascript
JS遍历对象属性的方法示例
2017/01/10 Javascript
Vue.js:使用Vue-Router 2实现路由功能介绍
2017/02/22 Javascript
关于javascript作用域的常见面试题分享
2017/06/18 Javascript
vue-router 权限控制的示例代码
2017/09/21 Javascript
js经验分享 JavaScript反调试技巧
2018/03/10 Javascript
基于mpvue搭建微信小程序项目框架的教程详解
2019/04/10 Javascript
layui内置模块layim发送图片添加加载动画的方法
2019/09/23 Javascript
微信小程序整个页面的自动适应布局的实现
2020/07/12 Javascript
[36:54]Mineski vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python二叉树遍历的实现方法
2013/11/21 Python
通过源码分析Python中的切片赋值
2017/05/08 Python
pygame实现弹力球及其变速效果
2017/07/03 Python
如何实现删除numpy.array中的行或列
2018/05/08 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
python3中rank函数的用法
2019/11/27 Python
基于Keras 循环训练模型跑数据时内存泄漏的解决方式
2020/06/11 Python
AmazeUI 加载进度条的实现示例
2020/08/20 HTML / CSS
法雷奥SQA(electric)面试问题
2016/01/23 面试题
外贸学院会计专业应届生求职信
2013/11/14 职场文书
结对共建协议书
2014/08/20 职场文书
上课随便讲话检讨书
2014/09/12 职场文书
中国文明网向国旗敬礼寄语大全
2014/09/27 职场文书
初中生思想道德自我评价
2015/03/09 职场文书
2015年学生会主席工作总结
2015/04/21 职场文书
《别在吃苦的年纪选择安逸》读后感3篇
2019/11/30 职场文书
JavaScript异步操作中串行和并行
2021/11/20 Javascript
阿里云k8s服务升级时502错误 springboot项目应用
2022/04/09 Servers