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陷阱清单
May 31 Javascript
ajax处理php返回json数据的实例代码
Jan 24 Javascript
JavaScript 处理Iframe自适应高度(同或不同域名下)
Mar 29 Javascript
详解JavaScript的while循环的使用
Jun 03 Javascript
JavaScript实现可拖拽的拖动层Div实例
Aug 05 Javascript
js实现C#的StringBuilder效果完整实例
Dec 22 Javascript
javascript HTML5 Canvas实现圆盘抽奖功能
Apr 11 Javascript
javascirpt实现2个iframe之间传值的方法
Jun 30 Javascript
JavaScript中校验银行卡号的实现代码
Dec 19 Javascript
JS图片轮播与索引变色功能实例详解
Jul 06 Javascript
解决vue-router 二级导航默认选中某一选项的问题
Nov 01 Javascript
javascript canvas API内容整理
Feb 16 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
php侧拉菜单 漂亮,可以向右或者向左展开,支持FF,IE
2009/10/15 PHP
PHP使用PHPMailer发送邮件的简单使用方法
2013/11/12 PHP
PHP Session机制简介及用法
2014/08/19 PHP
php fread读取文件注意事项
2016/09/24 PHP
highchart数据源纵轴json内的值必须是int(详解)
2017/02/20 PHP
Yii2设置默认控制器的两种方法
2017/05/19 PHP
javascript 面向对象编程基础 多态
2009/08/21 Javascript
jQuery+css+html实现页面遮罩弹出框
2013/03/21 Javascript
jQuery取得select选择的文本与值的示例
2013/12/09 Javascript
js实现延时加载Flash的方法
2015/11/26 Javascript
浅析AMD CMD CommonJS规范--javascript模块化加载学习心得总结
2016/03/16 Javascript
AngularJS控制器之间的通信方式详解
2016/11/03 Javascript
js和jquery中获取非行间样式
2017/05/05 jQuery
JS原生轮播图的简单实现(推荐)
2017/07/22 Javascript
JavaScript-定时器0~9抽奖系统详解(代码)
2017/08/16 Javascript
vue实现键盘输入支付密码功能
2018/08/18 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
解决qrcode.js生成二维码时必须定义一个空div的问题
2020/07/09 Javascript
Vue+Openlayers自定义轨迹动画
2020/09/24 Javascript
vue.js页面加载执行created,mounted的先后顺序说明
2020/11/07 Javascript
[01:22:10]Ti4 循环赛第二日 DK vs Empire
2014/07/11 DOTA
[01:58]2018DOTA2亚洲邀请赛趣味视频——交流
2018/04/03 DOTA
Python使用os模块和fileinput模块来操作文件目录
2016/01/19 Python
浅谈Python中用datetime包进行对时间的一些操作
2016/06/23 Python
Python实现将HTML转换成doc格式文件的方法示例
2017/11/20 Python
Python解析并读取PDF文件内容的方法
2018/05/08 Python
python获取url的返回信息方法
2018/12/17 Python
Python实现EXCEL表格的排序功能示例
2019/06/25 Python
python 批量修改 labelImg 生成的xml文件的方法
2019/09/09 Python
python3用urllib抓取贴吧邮箱和QQ实例
2020/03/10 Python
Pycharm配置autopep8实现流程解析
2020/11/28 Python
Windows和Linux动态库应用异同
2016/07/28 面试题
人力资源管理专业应届生求职信
2014/04/24 职场文书
网吧温馨提示
2015/07/17 职场文书
《圆的面积》教学反思
2016/02/19 职场文书
Feign调用传输文件异常的解决
2021/06/24 Java/Android