vue.js源码学习分享(九)
/* */ var arrayKeys = Object.getOwnPropertyNames(arrayMethods);//获取arrayMethods的属性名称 /**
* By default, when a reactive property is set, the new value is//默认情况下,当一个响应的属性被设置,新的值也转换成响应的。然而当经过向下支撑时,我们不想促使转换,因为这值也许是一个嵌套值在一个冻结的数据结构,转换它时将会失去最优化
* also converted to become reactive. However when passing down props,
* we don't want to force conversion because the value may be a nested value
* under a frozen data structure. Converting it would defeat the optimization.
*/
var observerState = {
shouldConvert: true,
isSettingProps: false
}; /**
* Observer class that are attached to each observed//观察者类被绑定到每一个观察对象,一旦绑定,这个观察者使目标对象的属性键转换到getter/setter方法,收集依赖和发送的更新
* object. Once attached, the observer converts target
* object's property keys into getter/setters that
* collect dependencies and dispatches updates.
*/
接下来是最关键的一部分
var Observer = function Observer (value) {
this.value = value;
this.dep = new Dep();
this.vmCount = 0;
def(value, '__ob__', this);//给value定义一个‘——ob——’属性,属性的值为这个Observer对象
if (Array.isArray(value)) {//判断是不是一个数组
var augment = hasProto
? protoAugment
: copyAugment;
augment(value, arrayMethods, arrayKeys);
this.observeArray(value);
} else {
this.walk(value);
}
}; /**
* Walk through each property and convert them into//walk方法穿过每一个属性并且把他们转换到getter或者setter方法。这个方法应当仅在value的类型为对象时候调用
* getter/setters. This method should only be called when
* value type is Object.
*/
Observer.prototype.walk = function walk (obj) {
var keys = Object.keys(obj);//获取对象的每个键
for (var i = 0; i < keys.length; i++) {
defineReactive$$1(obj, keys[i], obj[keys[i]]);
}
}; /**
* Observe a list of Array items.//观察一个数组项目的列表
*/
Observer.prototype.observeArray = function observeArray (items) {
for (var i = 0, l = items.length; i < l; i++) {
observe(items[i]);
}
}; // helpers /**
* Augment an target Object or Array by intercepting//增加一个目标对象或者数组通过用__proto__截取原型链
* the prototype chain using __proto__
*/
function protoAugment (target, src) {
/* eslint-disable no-proto */
target.__proto__ = src;
/* eslint-enable no-proto */
} /**
* Augment an target Object or Array by defining
* hidden properties.//增大一个目标对象或者数组通过定义隐藏的属性
*/
/* istanbul ignore next */
function copyAugment (target, src, keys) {
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
def(target, key, src[key]);
}
} /**
* Attempt to create an observer instance for a value,//尝试创建一个观察者实例化一个值
* returns the new observer if successfully observed,//返回一个新的观察者如果成功被观察
* or the existing observer if the value already has one.//如果值已经有一个了则返回存在的观察者
*/
function observe (value, asRootData) {
if (!isObject(value)) {//如果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
} /**
* Define a reactive property on an Object.//定义一个响应的属性在一个对象上
*/
function defineReactive$$1 (
obj,
key,
val,
customSetter
) {
var dep = new Dep(); var property = Object.getOwnPropertyDescriptor(obj, key);
if (property && property.configurable === false) {
return
} // cater for pre-defined getter/setters//满足预定义的 getter/setters
var getter = property && property.get;
var setter = property && property.set; var childOb = observe(val);
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
var value = getter ? getter.call(obj) : val;
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;
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if ("development" !== 'production' && customSetter) {
customSetter();
}
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
childOb = observe(newVal);
dep.notify();
}
});
} /**
* Set a property on an object. Adds the new property and
* triggers change notification if the property doesn't
* already exist.
*/
function set (obj, key, val) {
if (Array.isArray(obj)) {
obj.length = Math.max(obj.length, key);
obj.splice(key, 1, val);
return val
}
if (hasOwn(obj, key)) {
obj[key] = val;
return
}
var ob = obj.__ob__;
if (obj._isVue || (ob && ob.vmCount)) {
"development" !== 'production' && warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
);
return
}
if (!ob) {
obj[key] = val;
return
}
defineReactive$$1(ob.value, key, val);
ob.dep.notify();
return val
} /**
* Delete a property and trigger change if necessary.
*/
function del (obj, key) {
if (Array.isArray(obj)) {
obj.splice(key, 1);
return
}
var ob = obj.__ob__;
if (obj._isVue || (ob && ob.vmCount)) {
"development" !== 'production' && warn(
'Avoid deleting properties on a Vue instance or its root $data ' +
'- just set it to null.'
);
return
}
if (!hasOwn(obj, key)) {
return
}
delete obj[key];
if (!ob) {
return
}
ob.dep.notify();
} /**
* Collect dependencies on array elements when the array is touched, since
* we cannot intercept array element access like property getters.
*/
function dependArray (value) {
for (var e = (void 0), i = 0, l = value.length; i < l; i++) {
e = value[i];
e && e.__ob__ && e.__ob__.dep.depend();
if (Array.isArray(e)) {
dependArray(e);
}
}
}
vue.js源码学习分享(九)的更多相关文章
- vue.js源码学习分享(一)
今天看了vue.js源码 发现非常不错,想一边看一遍写博客和大家分享 /** * Convert a value to a string that is actually rendered. *转换 ...
- vue.js源码学习分享(七)
var _Set; /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) { // use ...
- vue.js源码学习分享(六)
/* */ /* globals MutationObserver *///全局变化观察者 // can we use __proto__?//我们能用__proto__吗? var hasProto ...
- vue.js源码学习分享(八)
/* */ var uid$1 = 0; /** * A dep is an observable that can have multiple * directives subscribing() ...
- vue.js源码学习分享(五)
//配置项var config = { /** * Option merge strategies (used in core/util/options)//选项合并策略 */ optionMerge ...
- vue.js源码学习分享(四)
/** * Generate a static keys string from compiler modules.//从编译器生成一个静态键字符串模块. */ function genStaticK ...
- vue.js源码学习分享(三)
/** * Mix properties into target object.//把多个属性插入目标的对象 */ function extend (to, _from) { for (var key ...
- vue.js源码学习分享(二)
/** * Check if value is primitive//检查该值是否是个原始值 */ function isPrimitive (value) { return typeof value ...
- Vue.js 源码学习笔记
最近饶有兴致的又把最新版 Vue.js 的源码学习了一下,觉得真心不错,个人觉得 Vue.js 的代码非常之优雅而且精辟,作者本身可能无 (bu) 意 (xie) 提及这些.那么,就让我来吧:) 程序 ...
随机推荐
- CentOS7 中使用 firewall-cmd 控制端口和端口转发
0X00 firewalld 守护进程 firewall-cmd命令需要firewalld进程处于运行状态.我们可以使用systemctl status/start/stop/restart fire ...
- 16Shell脚本—计划任务服务程序
计划任务服务程序 尽管我们现在已近有了功能彪悍的脚本程序来执行一些批处理工作,但是,如果仍然需要每天凌晨两点敲击键盘回车键来执行这个脚本程序,这简直太痛苦了.为此,我们需要学习如何设置服务器的计划任务 ...
- HDU:5040-Instrusive
Instrusive Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Proble ...
- Ubuntu首次登入与在线求助man page总结
1.为了避免瞬间断电造成的Linux系统的危害,建议做为服务器的Linux主机应该加上不断电系统来持续提供稳定的电力 2.默认的图形模式登入中,可以选择语系以及作业阶段.作业阶段为多种窗口管理员软件所 ...
- js---JSONP原理及使用
极简解释: 利用<script>标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的.当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址 ...
- .NET开发时让人头痛的SESSION超时
前言 不知道大家在使用用.NET的SESSION的时候有没有遇到过很奇怪的问题,不时候不知道怎么回事,这个SESSION就无缘无故的丢失了 怎么也想不通,不是说SESSION很可靠的吗?这个问题要好好 ...
- Selenium WebDriver-下拉框断言
#encoding=utf-8 import unittest import time import chardet from selenium import webdriver class Visi ...
- jquery版列表切换功能
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...
- TensorFlow——零碎语法知识点
张量(tensor) 张量 是图中计算节点的运算结果的引用,由name,shape,type三个属性构成. 张量的命名 可以以“name:src_output”的形式给出,node为计算节点名称,sr ...
- Python 协程、IO模型
1.协程(单线程实现并发)2.I/0模型 2.1阻塞I/O 2.2非阻塞I/O 知识点一:协程 协程的目的:是想要在单线程下实现并发(并发看起来是同时运行的) 并发=多个任务间切换+保存状态(正常情况 ...