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) 提及这些.那么,就让我来吧:) 程序 ...
随机推荐
- Java开发小游戏 用键盘控制精灵在游戏中上下左右跑动 窗体小游戏可打包下载,解压后双击start运行
package com.swift; import java.awt.Point; import java.awt.event.KeyEvent; import com.rupeng.game.Gam ...
- C++ 学习笔记(二) const的加强
const 含义为只读.如果在程序中显式改变const变量那么编译会报错. C语言的const: 在C语言中const 变量是放在内存中,如果使用指针可以间接改变const变量.所以在C语言中cons ...
- MySQL的GTID复制与传统复制的相互切换
MySQL的GTID复制与传统复制的相互转换 1. GTID复制转换成传统复制 1.1 环境准备 1.2 停止slave 1.3 查看当前主从状态 1.4 change master 1.5 启动主从 ...
- laravel连接数据库提示mysql_connect() :Connection refused...
在.env配置文件中填写了正确的数据库连接配置的情况下连接还是出错了,明显提示的不是密码错误,那就看看端口吧, DB_HOST=127.0.0.1 DB_PORT= DB_DATABASE=test ...
- w3resource_MySQL练习:Subquery
w3resource_MySQL练习题:Subquery 1. Write a query to find the name (first_name, last_name) and the salar ...
- 前端之bootstrap
一.响应式介绍 众所周知,电脑.平板.手机的屏幕是差距很大的,假如在电脑上写好了一个页面,在电脑上看起来不错,但是如果放到手机上的话,那可能就会乱的一塌糊涂,这时候怎么解决呢?以前,可以再专门为手机定 ...
- Linux下ioctl函数理解
一. 什么是ioctl ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的调用个数如下: i ...
- nuc 第二届山西省大学生程序设计大赛 魔力手环
problem 很妙啊--发现状态转移矩阵每一行都可以由上一行平移得到,每次只算第一行然后平移,\(O(n^3)\) 就变成了 \(O(n^2)\). #include <iostream> ...
- 编译参数-ObjC的说明
一些第三方库里对系统库的类加了 category , 这时,就需要使用编译参数: -ObjC ,这样第三方库中对系统类作的扩展方法才能在工程中使用. 但是使用 -Objc 后,会产生两个问题: 1 . ...
- XeLaTeX插入GB/T 7714-2005规范的参考文献方法
GB/T 7714-2005 biblatex 在使用XeLaTeX的过程中,会遇到参考文献需要按照GB/T 7714-2005规范的情况.此时需要使用biblatex宏包,并且指定包的参数为 ...