浅析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 21 Javascript
JavaScript Chart 插件整理
Jun 18 Javascript
从零开始学习jQuery (三) 管理jQuery包装集
Feb 23 Javascript
jquery.Jwin.js 基于jquery的弹出层插件代码
May 23 Javascript
JavaScript获取文本框内选中文本的方法
Feb 20 Javascript
jQuery EasyUI封装简化操作
Sep 18 Javascript
JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome
Jan 05 Javascript
利用JavaScript如何查询某个值是否数组内
Jul 30 Javascript
echart简介_动力节点Java学院整理
Aug 11 Javascript
mui back 返回刷新页面的实例
Dec 06 Javascript
小程序实现展开/收起的效果示例
Sep 22 Javascript
在vue项目实现一个ctrl+f的搜索功能
Feb 28 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 取得瑞年与平年的天数的代码
2009/08/10 PHP
163的邮件用phpmailer发送(实例详解)
2013/06/24 PHP
PHP下获取上个月、下个月、本月的日期(strtotime,date)
2014/02/02 PHP
将php数组输出html表格的方法
2014/02/24 PHP
php绘制一个扇形的方法
2015/01/24 PHP
php的闭包(Closure)匿名函数详解
2015/02/22 PHP
如何判断php mysqli扩展类是否开启
2016/12/24 PHP
php中目录操作opendir()、readdir()及scandir()用法示例
2019/06/08 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
jquery tools 系列 scrollable学习
2009/09/06 Javascript
基于jquery的关于动态创建DOM元素的问题
2010/12/24 Javascript
Javascript浮点数乘积运算出现多位小数的解决方法
2014/02/17 Javascript
javascript下拉框选项单击事件的例子分享
2015/03/04 Javascript
谈谈JavaScript异步函数发展历程
2015/09/29 Javascript
AngularJS中的Directive实现延迟加载
2016/01/25 Javascript
JavaScript制作弹出层效果
2016/12/02 Javascript
vue-cli + sass 的正确打开方式图文详解
2017/10/27 Javascript
angularjs获取到My97DatePicker选中的值方法
2018/10/02 Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
2020/11/16 Javascript
[49:08]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第一场 11.27
2020/12/01 DOTA
Python入门篇之编程习惯与特点
2014/10/17 Python
基于python实现音乐播放器代码实例
2020/07/01 Python
利用CSS3实现炫酷的飞机起飞动画
2016/09/17 HTML / CSS
Chemist Warehouse官方海外旗舰店:澳洲第一连锁大药房
2017/08/25 全球购物
马来西亚综合购物网站:Lazada马来西亚
2018/06/05 全球购物
牵手50香港:专为黄金岁月的单身人士而设的交友网站
2020/08/14 全球购物
如何查找和删除数据库中的重复数据
2014/11/05 面试题
营销人才自我鉴定范文
2013/12/25 职场文书
旷课检讨书大全
2014/01/21 职场文书
教师正风肃纪剖析材料
2014/10/20 职场文书
党组织领导班子整改方案
2014/10/25 职场文书
大学生求职自荐信
2015/03/24 职场文书
nginx搭建图片服务器的过程详解(root和alias的区别)
2021/03/31 Servers
MongoDB balancer的使用详解
2021/04/30 MongoDB
教你怎么用python selenium实现自动化测试
2021/05/27 Python
redis不能访问本机真实ip地址的解决方案
2021/07/07 Redis