开播了开播了!

  vue通过数据劫持来达到监听和操作DOM更新,上一节简述了数组变化是如何监听的,这一节先讲讲对象属性是如何劫持的。

    // Line-855
Observer.prototype.walk = function walk(obj) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
// Go!
defineReactive$$1(obj, keys[i], obj[keys[i]]);
}
};

  上一节说到这里,现在进入defineReactive$$1来看看具体的劫持过程,函数比较长。

  函数接受4个参数,分别为数据对象、键、值、默认设置,由于这里只传了3个,先不管第4个

    // Line-925
function defineReactive$$1(
obj,
key,
val,
customSetter
) {
// 生成一个依赖管理
var dep = new Dep();
// getOwnPropertyDescriptor方法以对象形式返回键描述信息
// 包括enumerable、writable等等
var property = Object.getOwnPropertyDescriptor(obj, key);
// 不可修改的键直接返回
if (property && property.configurable === false) {
return
} // 获取对应的getter与setter
var getter = property && property.get;
var setter = property && property.set;
// 值为对象时的嵌套监听
// 当前值为'Hello Vue'的字符串 直接返回
var childOb = observe(val);
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
// 有getter方法直接调用
var value = getter ? getter.call(obj) : val;
// 这里暂时为null
if (Dep.target) {
dep.depend();
if (childOb) {
childOb.dep.depend();
}
if (Array.isArray(value)) {
dependArray(value);
}
}
// 直接返回值
return value
},
set: function reactiveSetter(newVal) {
// 获取当前值
var value = getter ? getter.call(obj) : val;
// 这是比较个啥 只有NaN才会不等于自身吧
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
// 这个参数没传 暂时不知道干啥的
if ("development" !== 'production' && customSetter) {
customSetter();
}
// 调用默认setter方法或将新值赋给当前值
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
//
childOb = observe(newVal);
// 广播变化
dep.notify();
}
});
}

  这里很多方法跳不进去,所以没法调试看效果,等这个搞完,做数据变化调试的时候再来详细解释,目前将就看一下。

  

  由于value只有一个message键,所以一次就结束了,函数疯狂返回,然后回到了observe的构造函数:

    // Line-900
function observe(value, asRootData) {
if (!isObject(value)) {
return
}
var ob;
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__;
} else if (
observerState.shouldConvert &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
// 跑完这里
ob = new Observer(value);
}
if (asRootData && ob) {
ob.vmCount++;
}
return ob
}

  

  来看看搞了这么久,ob是个什么东西:

  

  dep是依赖收集数据,包含计数id和依赖数组subs,还有4个原型方法。

  value是被监听数据,除了数据本身,还添加了__ob__属性引用自身,自定义了get和set方法,计数的vmCount。

  原型方法包含一个遍历数组数据的observeArray与监听对象的walk方法。

  接下来的代码将vmCount加1,然后返回这个ob对象,返回到了initData函数:

    // Line-3012
function initData(vm) {
// ..格式化、代理
// ...
// 监听数据
observe(data, true /* asRootData */ );
}

  这个函数也到头了,返回到了initState函数:

    // Line-2948
function initState(vm) {
// ...
// 从这里跳了出来
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);
}
}

  好吧,这个也没啥执行的,返回到了最原始的_init初始化函数:

    // Line-3924
Vue.prototype._init = function(options) {
// ...各种初始化
// ...
// 从这里跳出来
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created'); /* istanbul ignore if */
if ("development" !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false);
mark(endTag);
measure(((vm._name) + " init"), startTag, endTag);
} if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
};

   接下来是initProvide函数,provide翻译成中文是准备的意思。

    // Line-3924
function initProvide(vm) {
// 没有这个属性 跳
var provide = vm.$options.provide;
if (provide) {
vm._provided = typeof provide === 'function' ?
provide.call(vm) :
provide;
}
}

  然后调用钩子函数,进入created阶段,由于没有定义执行内容,所以直接跳出来,代码就不贴了。

  那个dev内容也不太清楚记录的什么,暂时先不管,下面是双绑的另一个大模块:AST。

  本节先简单结束了,数据劫持也差不多这些,下一节开始跑节点挂载。

  上图:

.4-Vue源码之数据劫持(2)的更多相关文章

  1. Vue源码解析---数据的双向绑定

    本文主要抽离Vue源码中数据双向绑定的核心代码,解析Vue是如何实现数据的双向绑定 核心思想是ES5的Object.defineProperty()和发布-订阅模式 整体结构 改造Vue实例中的dat ...

  2. .3-Vue源码之数据劫持(1)

    写了一半关机了,又得重新写,好气. 上一节讲到initData函数,其中包含格式化.代理.监听. // Line-3011 function initData(vm) { var data = vm. ...

  3. [Vue源码]一起来学Vue双向绑定原理-数据劫持和发布订阅

    有一段时间没有更新技术博文了,因为这段时间埋下头来看Vue源码了.本文我们一起通过学习双向绑定原理来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫 ...

  4. vue源码之响应式数据

    分析vue是如何实现数据响应的. 前记 现在回顾一下看数据响应的原因. 之前看了vuex和vue-i18n的源码, 他们都有自己内部的vm, 也就是vue实例. 使用的都是vue的响应式数据特性及$w ...

  5. vue 快速入门 系列 —— 侦测数据的变化 - [vue 源码分析]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue 源码分析] 本文将 vue 中与数据侦测相关的源码摘了出来,配合上文(侦测数据的变化 - [基本实现]) 一起来分析一下 vue ...

  6. Vue源码解析之数组变异

    力有不逮的对象 众所周知,在 Vue 中,直接修改对象属性的值无法触发响应式.当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变. 这是什么原因? 原因在于: Vue 的响应式 ...

  7. Vue框架核心之数据劫持

    本文来自网易云社区. 前瞻 当前前端界空前繁荣,各种框架横空出世,包括各类mvvm框架横行霸道,比如Angular.Regular.Vue.React等等,它们最大的优点就是可以实现数据绑定,再也不需 ...

  8. Vue源码--解读vue响应式原理

    原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...

  9. 【Vuejs】350- 学习 Vue 源码的必要知识储备

    前言 我最近在写 Vue 进阶的内容.在这个过程中,有些人问我看 Vue 源码需要有哪些准备吗?所以也就有了这篇计划之外的文章. 当你想学习 Vue 源码的时候,需要有扎实的 JavaScript 基 ...

随机推荐

  1. 代码的完整性:打印1到最大的n位数

    输入数字n,按顺序打印出从1到最大的n位十进制数. 比如,输入3,则打印出1,2,3,.....,一直到最大的3位数即999. 全排列打印 public class Main { public sta ...

  2. 关于APP分享到QQ、微信等

    <script> var shares=null;        var Intent=null,File=null,Uri=null,main=null; function plusRe ...

  3. 深入理解计算机系统chapter9

    从概念上来讲:虚拟存储器被组织为一个存放在磁盘上的N个连续的字节大小的单元组成的数组. 磁盘上数组的内容被缓存到主存中 1. 读写内存的安全性 物理内存本身是不限制访问的,任何地址都可以读写,而操作系 ...

  4. 【Linux笔记(001) 】-- centos7 系统目录结构与文件

    一.目录结构与用途: /boot:系统引导文件.内核 /bin:用户的基本命令 /dev:设备文件 /etc:配置文件 /home:用户目录 /root:root用户目录 /sbin:管理类的基本命令 ...

  5. 第4章 同步控制 Synchronization ---哲学家进餐问题(The Dining Philosophers)

    哲学家进餐问题是这样子的:好几位哲学家围绕着餐桌坐,每一位哲学家要么思考,要么等待,要么就吃饭.为了吃饭,哲学家必须拿起两支筷子(分放于左右两端).不幸的是,筷子的数量和哲学家相等,所以每支筷子必须由 ...

  6. H5页面解决IOS进入不自动播放问题(微信内)

    废话少说,直接上代码. 主要还是调用微信的jdk做兼容处理.,安卓可自动播放. ($(function(){ $(function(){ /* ** 复选框*/ $('.ul-radio').on(' ...

  7. 关于高德地图Android开发时地图只显示一次、第二次打开不定位的解决办法

    我按照高德官方Demo改的 第一次是可以定位的,如左图 第二次就不能定位了,如右图 在onDestory中把aMap置为空即可 aMap = null; 修改完如下图: 原理是第二次打开时aMap不为 ...

  8. 剑指offer(纪念版) 面试题3:二维数组中的查找

    题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数.   第一种方法题目说不可行 ...

  9. 使用LayUI展示数据

    LayUI是一款免费,开源,轻量级的前端cms框架,适用于企业后端,能快速上手开发,集成了常用的组件,还有完善的文档和社区. 点击查看 文档地址 下载框架 使用: 1.把这个5个文件项都拷贝到项目中 ...

  10. Win7 32位系统下Sublime text 3的安装以及配置C/C++、java、python的开发环境方法

    本人初学者,此文仅是对这几天鼓捣subime text 3一点微不足道的经验总结,如有明显错误,欢迎指正! 好了,废话少说,进入正题,之前编程java一直用的是eclipse,java的主流IDE,后 ...