浅析vue数据绑定


Posted in Javascript onJanuary 17, 2017

前言:最近团队需要做一个分享,脚进脑子,不知如何分享。最后想着之前一直想研究一下 vue 源码,今天刚好 “借此机会” 研究一下。

网上研究vue数据绑定的文章已经非常多了,但是自己写一遍,敲一遍demo和看别人的文章是完全不同的,so……搬运工来了

目前数据绑定主要有以下三种实现方式:

1.   脏值检查(angular.js)    轮询检测数据变化

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

  • XHR响应事件 ( $http )
  • 浏览器Location变更事件 ( $location )
  • Timer事件( $timeout , $interval )
  • 执行 $digest() 或 $apply()

2、Object.defineProperty劫持对象的get、set,从而实现对数据的监控。 (vue)

3、发布/订阅者模式实现数据与视图的自动同步

Object.defineProperty的优点

  • “脏值检测”——数据发生变更后,对于所有的数据和视图的绑定关系进行一次检测,识别是否有数据发生了改变,有变化进行处理,可能进一步引发其他数据的改变,所以这个过程可能会循环几次,一直到不再有数据变化发生后,将变更的数据发送到视图,更新页面展现
  • Object.defineProperty() 监控对数据的操作,可以自动触发数据同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。

Object.defineProperty的用法

var a = {};

Object.defineProperty(a, "b", {
 
 set: function (newValue) {
 
 console.log("我被赋值了!" + newValue);
 
 },
 
 get: function () {
 
 console.log("我被取值了!");
 
 return 2 
 }
})

a.b = 3; //我被赋值了!

console.log(a.b); //我被取值了! //打印 2

由上面的例子看出,Object.defineProperty  传人3个参数

第一个: a对象

第二个: a对象里面的b属性

第三个: 属性比较多,列举有用的 value,set,get,configurable

数据绑定原理:

1、实现一个数据监听器Observer,对数据对象的所有属性进行监听,如有变动则拿到最新值并通知 dep数组

2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据

3、实现一个dep数组 ,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,更新视图

1. 实现observer

var data = {name: 'beidan'};

observe(data);

data.name = 'test'; // 监听到值变化了 beidan 变成 test

function observe(data) {
 
 if (!data || typeof data !== 'object') {
 
 return;
 
 }
 
 // 取出所有属性遍历
 
 Object.keys(data).forEach(function(key) {
 
  defineReactive(data, key, data[key]);

 });
}
function defineReactive(data, key, val) {


 Object.defineProperty(data, key, {

 enumerable: true, // 可枚举
 
  configurable: false, // 不能再define
  get: function() {
  
   return val;
 
  },
 
  set: function(newVal) {
  
   console.log('监听到值变化了 ', val, ' 变成 ', newVal);

   val = newVal;
 
  }
 
 });
}

2. 维护一个数组

function Dep() {
 
 this.subs = [];
}

Dep.prototype = {
 
 addSub: function (sub) {
 
 this.subs.push(sub);
 
 },
 
 notify: function (val) {
 
  this.subs.forEach(function (sub) {
  
  sub.update(val)
 
 });
 
}
};
function defineReactive(data, key, val) {
 Object.defineProperty(data, key, {
 ……
 set: function(newVal) {
  if (val === newVal) return;
  console.log('监听到值变化了 ', val, ' 变成 ', newVal);
  val = newVal;
  dep.notify(val); // 通知所有订阅者 
 } 
 });
}

3. compile

bindText: function () {
 
 var textDOMs = this.el.querySelectorAll('[v-text]'),
bindText,_context = this;

 
 for (var i = 0; i < textDOMs.length; i++) {
  
 bindText = textDOMs[i].getAttribute('v-text');
 textDOMs[i].innerHTML = this.data[bindText];

 var val = textDOMs[i]

 
 var up = function (text) {
  
  val.innerText = text
 
 }

 _context.dep.addSub({
  
  value: textDOMs[i],
  
  update: up
 
 });
 
 }
},

最后,附上源码 github   https://github.com/beidan/vue_bind

参考链接:

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

Javascript 相关文章推荐
JS中的构造函数详细解析
Mar 10 Javascript
jQuery通过扩展实现抖动效果的方法
Mar 11 Javascript
JavaScript统计字符串中每个字符出现次数完整实例
Jan 28 Javascript
React学习之事件绑定的几种方法对比
Sep 24 Javascript
vue.js $refs和$emit 父子组件交互的方法
Dec 20 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
Feb 10 Javascript
Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现
Apr 01 Javascript
jquery获取并修改触发事件的DOM元素示例【基于target 属性】
Oct 10 jQuery
JS实现关闭小广告特效
Jan 29 Javascript
JS数组方法reverse()用法实例分析
Jan 18 Javascript
原生js拖拽实现图形伸缩效果
Feb 10 Javascript
Vue两种组件类型:递归组件和动态组件的用法
Aug 06 Javascript
JavaScript使用正则表达式获取全部分组内容的方法示例
Jan 17 #Javascript
JavaScript使用delete删除数组元素用法示例【数组长度不变】
Jan 17 #Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
Jan 17 #Javascript
详谈JavaScript的闭包及应用
Jan 17 #Javascript
用原生js做单页应用
Jan 17 #Javascript
js cookie实现记住密码功能
Jan 17 #Javascript
angularjs ocLazyLoad分步加载js文件实例
Jan 17 #Javascript
You might like
php中sql注入漏洞示例 sql注入漏洞修复
2014/01/24 PHP
php实现Linux服务器木马排查及加固功能
2014/12/29 PHP
探究Laravel使用env函数读取环境变量为null的问题
2016/12/06 PHP
用Javascript实现锚点(Anchor)间平滑跳转
2009/09/08 Javascript
浅谈Javascript事件模拟
2012/06/27 Javascript
点弹代码 点击页面任何位置都可以弹出页面效果代码
2012/09/17 Javascript
利用yarn实现一个webpack+react种子
2016/10/25 Javascript
JS中数组重排序方法
2016/11/11 Javascript
关于javascript事件响应的基础语法总结(必看篇)
2016/12/26 Javascript
深入理解jquery的$.extend()、$.fn和$.fn.extend()
2017/07/08 jQuery
Angularjs 根据一个select的值去设置另一个select的值方法
2018/08/13 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
vue中实现回车键登录功能
2020/02/19 Javascript
[59:36]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第二场
2018/04/04 DOTA
查看Python安装路径以及安装包路径小技巧
2015/04/28 Python
Python正则表达式匹配中文用法示例
2017/01/17 Python
基于python socketserver框架全面解析
2017/09/21 Python
PyQt5利用QPainter绘制各种图形的实例
2017/10/19 Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
2018/02/08 Python
python按综合、销量排序抓取100页的淘宝商品列表信息
2018/02/24 Python
python+tkinter实现学生管理系统
2019/08/20 Python
查看端口并杀进程python脚本代码
2019/12/17 Python
解决pycharm中opencv-python导入cv2后无法自动补全的问题(不用作任何文件上的修改)
2020/03/05 Python
Django用户身份验证完成示例代码
2020/04/03 Python
django-orm F对象的使用 按照两个字段的和,乘积排序实例
2020/05/18 Python
python调用百度AI接口实现人流量统计
2021/02/03 Python
详解android与HTML混合开发总结
2018/06/06 HTML / CSS
Omio英国:搜索并比较便宜的巴士、火车和飞机
2019/08/27 全球购物
PatPat香港:婴童服饰和亲子全家装在线购物
2020/09/27 全球购物
美术师范毕业生自荐信
2013/11/16 职场文书
2014年中班元旦活动方案
2014/02/14 职场文书
地理教师岗位职责
2014/03/16 职场文书
医院搬迁方案
2014/06/14 职场文书
学校门卫岗位职责范本
2014/06/30 职场文书
工作目标责任书
2014/07/23 职场文书
JAVA长虹键法之建造者Builder模式实现
2022/04/10 Java/Android