浅析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(JavaScript)实现TAB标签切换效果的简单实例
Feb 26 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
Feb 26 Javascript
JavaScript中的变量作用域介绍
Dec 31 Javascript
在JSP中如何实现MD5加密的方法
Nov 02 Javascript
解析如何利用iframe标签以及js制作时钟
Dec 08 Javascript
利用JQuery实现datatables插件的增加和删除行功能
Jan 06 Javascript
vue项目如何刷新当前页面的方法
May 18 Javascript
vue中Element-ui 输入银行账号每四位加一个空格的实现代码
Sep 14 Javascript
小程序实现留言板
Nov 02 Javascript
JavaScript函数定义方法实例详解
Mar 05 Javascript
JavaScript中的惰性载入函数及优势
Feb 18 Javascript
javascript实现移动端上传图片功能
Aug 18 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
一个查看session内容的函数
2006/10/09 PHP
PHP多维数组遍历方法(2种实现方法)
2015/12/10 PHP
php官方微信接口大全(微信支付、微信红包、微信摇一摇、微信小店)
2015/12/21 PHP
利用PHP生成静态html页面的原理
2016/09/30 PHP
PHP 实现页面静态化的几种方法
2017/07/23 PHP
JavaScript版DateAdd和DateDiff函数代码
2012/03/01 Javascript
基于javascript实现判断移动终端浏览器版本信息
2014/12/09 Javascript
JS中判断字符串中出现次数最多的字符及出现的次数的简单实例
2016/06/03 Javascript
onmouseover事件和onmouseout事件全面理解
2016/08/15 Javascript
浅谈bootstrap使用中的一些问题以及解决过程
2016/10/18 Javascript
简单的js计算器实现
2016/10/26 Javascript
jQuery插件HighCharts绘制2D饼图效果示例【附demo源码下载】
2017/03/21 jQuery
Webpack实现按需打包Lodash的几种方法详解
2017/05/08 Javascript
详解react使用react-bootstrap当轮子造车
2017/08/15 Javascript
element-ui带输入建议的input框踩坑(输入建议空白以及会闪出上一次的输入建议问题)
2019/01/15 Javascript
js实现简单分页导航栏效果
2019/06/28 Javascript
关于ligerui子页面关闭后,父页面刷新,重新加载的方法
2019/09/27 Javascript
解决vue项目获取dom元素宽高总是不准确问题
2020/07/29 Javascript
原生JS实现弹幕效果的简单操作指南
2020/11/10 Javascript
js实现类选择器和name属性选择器的示例步骤
2021/02/07 Javascript
[43:51]2014 DOTA2国际邀请赛中国区预选赛 Dream Times VS TongFu
2014/05/22 DOTA
[01:03:41]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第一场 12.17
2020/12/19 DOTA
美国环保妈妈、儿童和婴儿用品购物网站:The Tot
2019/11/24 全球购物
优秀的教师个人的中文求职信
2013/09/21 职场文书
会计毕业生自荐信
2013/11/21 职场文书
优秀大学生推荐信范文
2013/11/28 职场文书
工厂保洁员岗位职责
2013/12/04 职场文书
共筑中国梦演讲稿
2014/04/23 职场文书
投标承诺书怎么写
2014/05/24 职场文书
证劵公司反洗钱宣传活动总结
2015/05/08 职场文书
毕业论文答辩演讲稿
2015/06/23 职场文书
矛盾论读书笔记
2015/06/29 职场文书
2016年春季运动会加油稿
2015/07/22 职场文书
完美处理python与anaconda环境变量的冲突问题
2021/04/07 Python
安装pytorch时报sslerror错误的解决方案
2021/05/17 Python
实现GO语言对数组切片去重
2022/04/20 Golang