浅析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 相关文章推荐
兼容IE和Firefox的javascript获取iframe文档内容的函数
Aug 15 Javascript
jquery.boxy弹出框(后隔N秒后自动隐藏/自动跳转)
Jan 15 Javascript
JS中怎样判断undefined(比较不错的方法)
Mar 27 Javascript
bootstrap布局中input输入框右侧图标点击功能
May 16 Javascript
js省市县三级联动效果实例
Apr 15 Javascript
js实现为a标签添加事件的方法(使用闭包循环)
Aug 02 Javascript
深入浅析Vue组件开发
Nov 25 Javascript
基于daterangepicker日历插件使用参数注意的问题
Aug 10 Javascript
JavaScript实现图片本地预览功能【不用上传至服务器】
Sep 20 Javascript
深入理解es6块级作用域的使用
Mar 28 Javascript
详解微信小程序胶囊按钮返回|首页自定义导航栏功能
Jun 14 Javascript
浅谈Node新版本13.2.0正式支持ES Modules特性
Nov 25 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
Linux编译升级php的详细方法
2013/11/04 PHP
php禁止浏览器使用缓存页面的方法
2014/11/07 PHP
php中simplexml_load_file函数用法实例
2014/11/12 PHP
yii去掉必填项中星号的方法
2015/12/28 PHP
PHP中的表达式简述
2016/05/29 PHP
php+js实现百度地图多点标注的方法
2016/11/30 PHP
PHP排序算法之快速排序(Quick Sort)及其优化算法详解
2018/04/21 PHP
Thinkphp极验滑动验证码实现步骤解析
2020/11/24 PHP
Extjs列表详细信息窗口新建后自动加载解决方法
2010/04/02 Javascript
jQuery EasyUI API 中文文档 搜索框
2011/09/29 Javascript
Function.prototype.call.apply结合用法分析示例
2013/07/03 Javascript
jQuery使用andSelf()来包含之前的选择集
2014/05/19 Javascript
node.js中的fs.chownSync方法使用说明
2014/12/16 Javascript
JavaScript中继承用法实例分析
2015/05/16 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
2015/10/27 Javascript
JavaScript作用域示例详解
2016/07/07 Javascript
jQuery Ajax请求后台数据并在前台接收
2016/12/10 Javascript
微信小程序 PHP后端form表单提交实例详解
2017/01/12 Javascript
用React实现一个完整的TodoList的示例代码
2017/10/30 Javascript
vue实现的微信机器人聊天功能案例【附源码下载】
2019/02/18 Javascript
详解JavaScript函数callee、call、apply的区别
2019/03/08 Javascript
js基础之事件捕获与冒泡原理
2019/10/09 Javascript
JavaScript读取本地文件常用方法流程解析
2020/10/12 Javascript
Python Tkinter基础控件用法
2014/09/03 Python
Python返回真假值(True or False)小技巧
2015/04/10 Python
利用python发送和接收邮件
2016/09/27 Python
利用python打开摄像头及颜色检测方法
2018/08/03 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
2019/07/04 Python
Python实现快速大文件比较代码解析
2020/09/04 Python
HTML5+css3:3D旋转木马效果相册
2017/01/03 HTML / CSS
韩国邮政旗下生鲜食品网上超市:epost
2016/08/27 全球购物
英国复古服装和球衣购买网站:3Retro Football
2018/07/09 全球购物
简述使用ftp进行文件传输时的两种登录方式?它们的区别是什么?常用的ftp文件传输命令是什么?
2016/11/20 面试题
2014年医院后勤工作总结
2014/12/06 职场文书
毕业酒会致辞
2015/07/29 职场文书
幼儿教师远程研修感悟
2015/11/18 职场文书