浅析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限制文本框输入长度两种限制方式(长度、字节数)
Dec 19 Javascript
原生javascript和jquery判断浏览器版本等信息
Jul 04 Javascript
jQuery插件实现表格隔行换色且感应鼠标高亮行变色
Sep 22 Javascript
JS 新增Cookie 取cookie值 删除cookie 举例详解
Oct 10 Javascript
javascript制作的cookie封装及使用指南
Jan 02 Javascript
jQuery基于图层模仿五星星评价功能的方法
May 07 Javascript
js在ie下打开对话窗口的方法小结
Oct 24 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
May 24 Javascript
全选复选框JavaScript编写小结(附代码)
Aug 16 Javascript
Angular实现的简单定时器功能示例
Dec 28 Javascript
angularjs性能优化的方法
Sep 05 Javascript
Vue监听一个数组id是否与另一个数组id相同的方法
Sep 26 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
人族 Terran 基本策略
2020/03/14 星际争霸
PHP中如何定义和使用常量
2013/02/28 PHP
PHP输出英文时间日期的安全方法(RFC 1123格式)
2014/06/13 PHP
PHP调用API接口实现天气查询功能的示例
2017/09/21 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
2019/03/12 PHP
fix-ie5.js扩展在IE5下不能使用的几个方法
2007/08/20 Javascript
网页开发中的容易忽略的问题 javascript HTML中的table
2009/04/15 Javascript
jQuery实现原理的模拟代码 -6 代码下载
2010/08/16 Javascript
jQuery EasyUI API 中文文档 - Menu菜单
2011/10/03 Javascript
用原生js做个简单的滑动效果的回到顶部
2014/10/15 Javascript
javascript中alert()与console.log()的区别
2015/08/26 Javascript
分享jQuery插件的学习笔记
2016/01/14 Javascript
详解vue移动端日期选择组件
2018/02/22 Javascript
Express之托管静态文件的方法
2018/06/01 Javascript
vue.js中proxyTable 转发请求的实现方法
2018/09/20 Javascript
vue2.0 如何在hash模式下实现微信分享
2019/01/22 Javascript
vue 实现在同一界面实现组件的动态添加和删除功能
2020/06/16 Javascript
深度剖析使用python抓取网页正文的源码
2014/06/11 Python
matplotlib在python上绘制3D散点图实例详解
2017/12/09 Python
基于Python Numpy的数组array和矩阵matrix详解
2018/04/04 Python
Python并发:多线程与多进程的详解
2019/01/24 Python
使用python来调用CAN通讯的DLL实现方法
2019/07/03 Python
python中append实例用法总结
2019/07/30 Python
python 上下文管理器及自定义原理解析
2019/11/19 Python
Django restframework 框架认证、权限、限流用法示例
2019/12/21 Python
澳大利亚运动鞋零售商:The Athlete’s Foot
2018/11/04 全球购物
UNOde50美国官网:西班牙珠宝品牌
2020/08/15 全球购物
档案检查欢迎词
2014/01/13 职场文书
学校爱心捐款倡议书
2014/05/13 职场文书
反腐倡廉标语
2014/06/24 职场文书
防灾减灾标语
2014/10/07 职场文书
教师政风行风评议心得体会
2014/10/21 职场文书
2015年求职自荐信范文
2015/03/04 职场文书
2015年计划生育责任书
2015/05/08 职场文书
100句拼搏进取的名言警句,值得一读!
2019/10/07 职场文书
Python用any()函数检查字符串中的字母以及如何使用all()函数
2022/04/14 Python