浅析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 继承详解(一)
Jul 13 Javascript
jquery select多选框的左右移动 具体实现代码
Jul 03 Javascript
JavaScript实现更改网页背景与字体颜色的方法
Feb 02 Javascript
jQuery实现鼠标悬停背景翻转的黑色导航菜单代码
Sep 14 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
Dec 31 Javascript
angular.js4使用 RxJS 处理多个 Http 请求
Sep 23 Javascript
原生JS实现多个小球碰撞反弹效果示例
Jan 31 Javascript
vue实现密码显示隐藏切换功能
Feb 23 Javascript
原生js实现移动端Touch轮播图的方法步骤
Jan 03 Javascript
微信小程序系列之自定义顶部导航功能
May 21 Javascript
vux-scroller实现移动端上拉加载功能过程解析
Oct 08 Javascript
VSCode写vue项目一键生成.vue模版,修改定义其他模板的方法
Apr 17 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中对各种加密算法、Hash算法的速度测试对比代码
2014/07/08 PHP
PHP使用JpGraph绘制折线图操作示例【附源码下载】
2019/10/18 PHP
通过JavaScript控制字体大小的代码
2011/10/04 Javascript
js实现的map方法示例代码
2014/01/13 Javascript
jQuery实现页面内锚点平滑跳转特效的方法总结
2015/05/11 Javascript
详解JavaScript ES6中的模板字符串
2015/07/28 Javascript
JavaScript修改作用域外变量的方法
2016/03/25 Javascript
基于jQuery倒计时插件实现团购秒杀效果
2016/05/13 Javascript
jQuery中 $ 符号的冲突问题及解决方案
2016/11/04 Javascript
jQuery图片轮播功能实例代码
2017/01/29 Javascript
AngularJS双向绑定和依赖反转实例详解
2017/04/15 Javascript
浅析JavaScript中的平稳退化(graceful degradation)
2017/07/24 Javascript
JS去掉字符串末尾的标点符号及删除最后一个字符的方法
2017/10/24 Javascript
bootstrap paginator分页插件的两种使用方式实例详解
2017/11/14 Javascript
深入理解js 中async 函数的含义和用法
2018/05/13 Javascript
基于js Canvas实现二次贝塞尔曲线
2018/12/25 Javascript
Selenium执行Javascript脚本参数及返回值过程详解
2020/04/01 Javascript
解决Vue router-link绑定事件不生效的问题
2020/07/22 Javascript
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
[01:00:14]2018DOTA2亚洲邀请赛 4.6 淘汰赛 VP vs TNC 第三场
2018/04/10 DOTA
小议Python中自定义函数的可变参数的使用及注意点
2016/06/21 Python
Python3 处理JSON的实例详解
2017/10/29 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
2017/11/21 Python
Python爬虫天气预报实例详解(小白入门)
2018/01/24 Python
python中的decorator的作用详解
2018/07/26 Python
选择python进行数据分析的理由和优势
2019/06/25 Python
pytorch 归一化与反归一化实例
2019/12/31 Python
Python基于argparse与ConfigParser库进行入参解析与ini parser
2021/02/02 Python
html5视频播放_动力节点Java学院整理
2017/07/13 HTML / CSS
护理自我鉴定范文
2013/10/06 职场文书
中青班党性分析材料
2014/02/16 职场文书
室内设计专业自荐信
2014/05/31 职场文书
钢琴师观后感
2015/06/12 职场文书
详解MySQL主从复制及读写分离
2021/05/07 MySQL
Vue vee-validate插件的简单使用
2021/06/22 Vue.js
Fluentd搭建日志收集服务
2022/09/23 Servers