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现实多行信息
Aug 26 Javascript
javascript 中__proto__和prototype详解
Nov 25 Javascript
Javascript Object 对象学习笔记
Dec 17 Javascript
js 获取元素所有兄弟节点的实现方法
Sep 06 Javascript
jQuery实现ToolTip元素定位显示功能示例
Nov 23 Javascript
js事件冒泡与事件捕获详解
Feb 20 Javascript
vue组件之Alert的实现代码
Oct 17 Javascript
微信小程序表单验证功能完整实例
Dec 01 Javascript
Vue项目history模式下微信分享爬坑总结
Mar 29 Javascript
layui之table checkbox初始化时选中对应选项的方法
Sep 02 Javascript
Vue使用axios引起的后台session不同操作
Aug 14 Javascript
如何用JavaScipt测网速
May 09 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
怎样辨别一杯好咖啡
2021/03/03 新手入门
印尼林东PWN黄金曼特宁咖啡豆:怎么冲世界上最醇厚的咖啡冲煮教程
2021/03/03 冲泡冲煮
php实现监听事件
2013/11/06 PHP
详解使用php调用微信接口上传永久素材
2017/04/11 PHP
laravel model模型处理之修改查询或修改字段时的类型格式案例
2019/10/17 PHP
通过PHP实现用户注册后邮箱验证激活
2020/11/10 PHP
javascript 冒号 使用说明
2009/06/06 Javascript
javascript EXCEL 操作类代码
2009/07/30 Javascript
一个js拖拽的效果类和dom-drag.js浅析
2010/07/17 Javascript
jQuery 选择器项目实例分析及实现代码
2012/12/28 Javascript
JavaScript中json使用自己总结
2013/08/13 Javascript
在AngularJS中使用AJAX的方法
2015/06/17 Javascript
AngularJS在IE下取数据总是缓存问题的解决方法
2016/08/05 Javascript
EasyUI为Numberbox添加blur事件的方法
2017/03/05 Javascript
js is_valid_filename验证文件名的函数
2017/07/19 Javascript
详谈Node.js之操作文件系统
2017/08/29 Javascript
vue实现长图垂直居上 vue实现短图垂直居中
2017/10/18 Javascript
Vue.js2.0中的变化小结
2017/10/24 Javascript
在Vue环境下利用worker运行interval计时器的步骤
2019/08/01 Javascript
简单了解JavaScript弹窗实现代码
2020/05/07 Javascript
详解设计模式中的工厂方法模式在Python程序中的运用
2016/03/02 Python
Python I/O与进程的详细讲解
2019/03/08 Python
使用python批量修改文件名的方法(视频合并时)
2020/03/24 Python
python hash每次调用结果不同的原因
2019/11/21 Python
PyTorch中的padding(边缘填充)操作方式
2020/01/03 Python
python 多线程爬取壁纸网站的示例
2021/02/20 Python
CSS3实现精美横向滚动菜单按钮
2017/04/14 HTML / CSS
CSS3绘制超炫的上下起伏波动进度加载动画
2016/04/21 HTML / CSS
详解如何在css3打包后自动追加前缀插件:autoprefixer
2018/12/18 HTML / CSS
英国森林假期:Forest Holidays
2021/01/01 全球购物
介绍一下MD5加密算法
2016/11/12 面试题
工商学院毕业生个人自我评价
2013/09/19 职场文书
自荐信格式
2013/12/01 职场文书
幼儿园秋游感想
2014/03/12 职场文书
党员领导干部廉洁从政承诺书
2014/03/27 职场文书
俄罗斯十大城市人口排名,第三首都仅排第六,第二是北方首都
2022/03/20 杂记