浅析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 相关文章推荐
一实用的实现table排序的Javascript类库
Sep 12 Javascript
滚动图片效果 jquery实现回旋滚动效果
Jan 08 Javascript
JavaScript改变HTML元素的样式改变CSS及元素属性
Nov 12 Javascript
JS使用cookie设置样式的方法
Jun 30 Javascript
Javascript单例模式的介绍和实例
Oct 08 Javascript
jquery获取table指定行和列的数据方法(当前选中行、列)
Nov 07 Javascript
基于iscroll.js实现下拉刷新和上拉加载效果
Nov 28 Javascript
微信小程序开发之改变data中数组或对象的某一属性值
Jul 05 Javascript
简单两步使用node发送qq邮件的方法
Mar 01 Javascript
element-ui tooltip修改背景颜色和箭头颜色的实现
Dec 16 Javascript
基于vue-draggable 实现三级拖动排序效果
Jan 10 Javascript
vue element-ul实现展开和收起功能的实例代码
Nov 25 Vue.js
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
怎样辨别一杯好咖啡
2021/03/03 新手入门
PHP字符转义相关函数小结(php下的转义字符串)
2007/04/12 PHP
PHP 多进程 解决难题
2009/06/22 PHP
PHP中的排序函数sort、asort、rsort、krsort、ksort区别分析
2014/08/18 PHP
jQuery 第二课 操作包装集元素代码
2010/03/14 Javascript
jquery获取下拉列表的值为null的解决方法
2011/03/18 Javascript
自己动手制作jquery插件之自动添加删除行的实现
2011/10/13 Javascript
jQuery实现图片文字淡入淡出效果
2015/12/21 Javascript
jQuery实现拖拽页面元素并将其保存到cookie的方法
2016/06/12 Javascript
微信小程序 删除项目工程实现步骤
2016/11/10 Javascript
基于jQuery实现滚动切换效果
2016/12/02 Javascript
hammer.js实现图片手势放大效果
2017/08/29 Javascript
原生JS控制多个滚动条同步跟随滚动效果
2017/12/22 Javascript
angularJS自定义directive之带参方法传递详解
2018/10/09 Javascript
TypeScript开发Node.js程序的方法
2019/04/30 Javascript
vuex 中插件的编写案例解析
2019/06/10 Javascript
JavaScript常用工具函数汇总(浏览器环境)
2020/09/17 Javascript
Python中对元组和列表按条件进行排序的方法示例
2015/11/10 Python
Python在Console下显示文本进度条的方法
2016/02/14 Python
Python字符串处理实例详解
2017/05/18 Python
python实现的汉诺塔算法示例
2019/10/23 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
PyQt5 文本输入框自动补全QLineEdit的实现示例
2020/05/13 Python
Python轻量级web框架bottle使用方法解析
2020/06/13 Python
python日志通过不同的等级打印不同的颜色(示例代码)
2021/01/13 Python
如何查看python关键字
2021/01/17 Python
css3实现背景颜色渐变让图片不再是唯一的实现方式
2012/12/18 HTML / CSS
浅析css3中matrix函数的使用
2016/06/06 HTML / CSS
localstorage和sessionstorage使用记录(推荐)
2017/05/23 HTML / CSS
婴儿鞋,独特的婴儿服装和配件:Zutano
2018/11/03 全球购物
软件测试常见笔试题
2012/02/04 面试题
什么是ESB?请介绍一下ESB?
2015/05/27 面试题
财务管理专业毕业生求职信范文
2013/09/21 职场文书
慰问信格式
2015/02/14 职场文书
Python Pycharm虚拟下百度飞浆PaddleX安装报错问题及处理方法(亲测100%有效)
2021/05/24 Python
python工具dtreeviz决策树可视化和模型可解释性
2022/03/03 Python