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 相关文章推荐
jquery 年会抽奖程序
Dec 22 Javascript
jquery animate实现鼠标放上去显示离开隐藏效果
Jul 21 Javascript
浏览器中url存储的JavaScript实现
Jul 07 Javascript
jQuery选择器用法实例详解
Dec 17 Javascript
动态创建按钮的JavaScript代码
Jan 29 Javascript
jQuery validate验证插件使用详解
May 11 Javascript
jquery实现网站列表切换效果的2种方法
Aug 12 Javascript
基于jQuery实现左侧菜单栏可折叠功能
Dec 27 Javascript
Javascript Function.prototype.bind详细分析
Dec 29 Javascript
angular2 ng build部署后base文件路径问题详细解答
Jul 15 Javascript
JavaScript命令模式原理与用法实例详解
Mar 10 Javascript
vue项目实现设置根据路由高亮对应的菜单项操作
Aug 06 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 zlib压缩和解压缩swf文件的代码
2008/12/30 PHP
php线性表顺序存储实现代码(增删查改)
2012/02/16 PHP
将PHP程序中返回的JSON格式数据用gzip压缩输出的方法
2016/03/03 PHP
php自定义时间转换函数示例
2016/12/07 PHP
php实现PDO中捕获SQL语句错误的方法
2017/02/16 PHP
详解使用php-cs-fixer格式化代码
2020/09/16 PHP
javascript读取RSS数据
2007/01/20 Javascript
ExtJs之带图片的下拉列表框插件
2010/03/04 Javascript
用apply让javascript函数仅执行一次的代码
2010/06/27 Javascript
关于JavaScript中的关联数组分析
2013/04/09 Javascript
使用jQuery避免鼠标双击的解决方案
2013/08/21 Javascript
jQuery移除元素自动解绑事件实现思路及代码
2014/05/31 Javascript
jquery根据属性和index来查找属性值并操作
2014/07/25 Javascript
JS+CSS实现可拖拽的漂亮圆角特效弹出层完整实例
2015/02/13 Javascript
轻松学习jQuery插件EasyUI EasyUI创建CRUD应用
2015/11/30 Javascript
基于jQuery实现歌词滚动版音乐播放器的代码
2016/09/17 Javascript
AngularJS实现表单验证功能
2017/01/09 Javascript
nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEqual()比较
2017/09/18 NodeJs
微信小程序入门之广告条实现方法示例
2018/12/05 Javascript
element-ui 时间选择器限制范围的实现(随动)
2019/01/09 Javascript
JS+CSS3实现的简易钟表效果示例
2019/04/13 Javascript
通过实例了解JS 连续赋值
2019/09/24 Javascript
JavaScript键盘事件响应顺序详解
2019/09/30 Javascript
vue 实现LED数字时钟效果(开箱即用)
2019/12/08 Javascript
基于vue+echarts 数据可视化大屏展示的方法示例
2020/03/09 Javascript
JavaScript布尔运算符原理使用解析
2020/05/06 Javascript
jQuery编写QQ简易聊天框
2020/08/27 jQuery
[04:36]DOTA2国际邀请赛 ti3精彩集锦
2013/08/19 DOTA
python使用Tesseract库识别验证
2018/03/21 Python
python实现网页自动签到功能
2019/01/21 Python
Canvas与Image互相转换示例代码
2013/08/09 HTML / CSS
公司门卫的岗位职责
2014/02/19 职场文书
人力资源经理的岗位职责范本
2014/02/28 职场文书
从事会计工作年限证明
2015/06/23 职场文书
解决ObjectMapper.convertValue() 遇到的一些问题
2021/06/30 Java/Android
Java版 简易五子棋小游戏
2022/05/04 Java/Android