浅析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 相关文章推荐
JavaScript在IE中“意外地调用了方法或属性访问”
Nov 19 Javascript
js split 的用法和定义 js split分割字符串成数组的实例代码
May 13 Javascript
关于全局变量和局部变量的那些事
Jan 11 Javascript
JS 数字转换研究总结
Dec 26 Javascript
基于JavaScript代码实现微信扫一扫下载APP
Dec 30 Javascript
最原始的jQuery注册验证方式
Oct 11 Javascript
详解Vue爬坑之vuex初识
Jun 14 Javascript
微信小程序图片选择区域裁剪实现方法
Dec 02 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
Feb 10 Javascript
Vue 监听列表item渲染事件方法
Sep 06 Javascript
jQuery实现的点击图片居中放大缩小功能示例
Jan 16 jQuery
了解javascript中let和var及const关键字的区别
May 24 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 三维饼图的实现代码
2008/09/28 PHP
php中长文章分页显示实现代码
2012/09/29 PHP
EXT窗口Window及对话框MessageBox
2011/01/27 Javascript
基于jQuery的简单的列表导航菜单
2011/03/02 Javascript
提高NodeJS中SSL服务的性能
2014/07/15 NodeJs
javascript中数组的定义及使用实例
2015/01/21 Javascript
javascript实现滚动效果的数字时钟实例
2016/07/21 Javascript
jQuery实现图片轮播效果代码
2016/09/27 Javascript
js字符串与Unicode编码互相转换
2017/05/17 Javascript
javascript checkbox/radio onchange不能兼容ie8处理办法
2017/06/13 Javascript
vue-awesome-swiper滑块插件使用方法详解
2017/11/27 Javascript
浅谈VUE监听窗口变化事件的问题
2018/02/24 Javascript
vue项目在线上服务器访问失败原因分析
2020/08/14 Javascript
原生JS实现拖拽效果
2020/12/04 Javascript
[35:26]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第三局
2016/02/26 DOTA
使用python绘制人人网好友关系图示例
2014/04/01 Python
python中list列表的高级函数
2016/05/17 Python
Python 数据处理库 pandas进阶教程
2018/04/21 Python
python 为什么说eval要慎用
2019/03/26 Python
flask框架jinja2模板与模板继承实例分析
2019/08/01 Python
Python如何调用外部系统命令
2019/08/07 Python
Python如何使用OS模块调用cmd
2020/02/27 Python
python应用Axes3D绘图(批量梯度下降算法)
2020/03/25 Python
Python求凸包及多边形面积教程
2020/04/12 Python
Keras自定义IOU方式
2020/06/10 Python
Python列表的深复制和浅复制示例详解
2021/02/12 Python
深入剖析webstorage[html5的本地数据处理]
2016/07/11 HTML / CSS
使用phonegap检测网络状态的方法
2017/03/30 HTML / CSS
SmartBuyGlasses台湾:名牌眼镜,名牌太阳眼镜及隐形眼镜
2017/01/04 全球购物
英国街头品牌:Bee Inspired Clothing
2018/02/12 全球购物
美国二手复古奢侈品包包购物网站:LXRandCo
2019/06/18 全球购物
建筑工程自我鉴定
2013/10/18 职场文书
社保缴纳证明申请书
2014/11/03 职场文书
家装电话营销开场白
2015/05/29 职场文书
OpenCV-Python实现轮廓的特征值
2021/06/09 Python
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript