Vue数据监听

参考文章:
https://www.jb51.net/article/124439.htm
http://www.php.cn/js-tutorial-393678.html
https://www.jianshu.com/p/1032ecd62b3a
https://www.cnblogs.com/leaf930814/p/9014200.html
http://www.php.cn/js-tutorial-393678.html
https://blog.csdn.net/it_rod/article/details/79516578

通过源码分析Vue的双向数据绑定详解

Vue源码的整体架构无非是初始化Vue对象,挂载数据data/props等,在不同的时期触发不同的事件钩子,如created() / mounted() / update()等,后面专门整理各个模块的文章。这里先讲双向数据绑定的部分,也是最主要的部分。
设计思想:观察者模式
Vue的双向数据绑定的设计思想为观察者模式,为了方便,下文中将被观察的对象称为观察者,将观察者对象触发更新的称为订阅者。主要涉及到的概念有:
1、Dep对象:Dependency依赖的简写,包含有三个主要属性id, subs, target和四个主要函数addSub, removeSub, depend, notify,是观察者的依赖集合,负责在数据发生改变时,使用notify()触发保存在subs下的订阅列表,依次更新数据和DOM。
id: 每个观察者(依赖对象)的唯一标识。
subs: 观察者对象的订阅者列表。
target: 全局唯一的订阅者对象,因为只能同时计算和更新一个订阅者的值。
addSub(): 使用push()方法添加一个订阅者。
removeSub(): 使用splice()方法移除一个订阅者。
depend(): 将自己添加到当前订阅者对象的依赖列表。
notify(): 在数据被更新时,会遍历subs对象,触发每一个订阅者的更新。
2、Observer对象:即观察者,包含两个主要属性value, dep。做法是使用getter/setter方法覆盖默认的取值和赋值操作,将对象封装为响应式对象,每一次调用时更新依赖列表,更新值时触发订阅者。绑定在对象的__ob__原型链属性上。
value: 原始值。
dep: 依赖列表。
源码实战解析
有过Vue开发基础的应该都了解其怎么初始化一个Vue对象:

new Vue({
   
 el: '#container',
 data: {
   
  count: 100
 },
 ...
});

那么我们就从这个count说起,看它是怎么完成双向数据绑定的。
下面的代码片段中英文注释为尤雨溪所写,中文注释为我所写,英文注释更能代表开发者的清晰思路。
首先从全局的初始化函数调用:initMixin(Vue$3); ,这里的Vue$3对象就是全局的Vue对象,在此之前已经挂载了Vue的各种基本数据和函数。这个函数体就是初始化我们上面声明Vue语句的过程化逻辑,取主体代码来看:

// 这里的options就是上面声明Vue对象的json对象
Vue.prototype._init = function (options) {
   
 ...
 var vm = this;
 ...
 initLifecycle(vm);
 initEvents(vm);
 initRender(vm);
 callHook(vm, 'beforeCreate');
 // 这里就是我们接下来要跟进的初始化Vue参数
 initState(vm);
 initInjections(vm);
 callHook(vm, 'created');
 ...
 };

这里主要完成了初始化事件、渲染、参数、注入等过程,并不断调用事件钩子的回调函数。下面来到如何初始化参数:

function initState (vm) {
   
 vm._watchers = [];
 var opts = vm.$options;
 if (opts.props) {
    initProps(vm, opts.props); }
 if (opts.methods) {
    initMethods(vm, opts.methods); }
 // 我们的count在这里初始化
 if (opts.data) {
   
 initData(vm);
 } else {
   
 observe(vm._data = {
   }, true /* asRootData */);
 }
 if (opts.computed) {
    initComputed(vm, opts.computed); }
 if (opts.watch) {
    initWatch(vm, opts.watch); }
}

这里依次检测参数中包含的props/methods/data/computed/watch并进入不同的函数进行初始化,这里我们只关心initData:

function initData (vm) {
   
 var data = vm.$options.data;
 data = vm._data = typeof data === 'function'
 ? data.call(vm)
 : data 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值