vuejs源码摘抄(二)
创建一个用来观察对象的observe类,这个类会附加在被观察的对象上,并且把被观察对象的属性值转换成getter/setter,同时,收集依赖和分发更新,实现代码如下:
/*
* not type checking this file because flow doesn't play well with
* dynamically accessing methods on Array prototype
*/ var arrayProto = Array.prototype;
var arrayMethods = Object.create(arrayProto);[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
.forEach(function (method) {
// cache original method
var original = arrayProto[method];
def(arrayMethods, method, function mutator () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ]; var result = original.apply(this, args);
var ob = this.__ob__;
var inserted;
switch (method) {
case 'push':
case 'unshift':
inserted = args;
break
case 'splice':
inserted = args.slice(2);
break
}
if (inserted) { ob.observeArray(inserted); }
// notify change
ob.dep.notify();
return result
});
}); /* */ var arrayKeys = Object.getOwnPropertyNames(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
}; /**
* Observer class that are attached to each observed
* 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);
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
* 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(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
* the prototype chain using __proto__
*/
function protoAugment (target, src, keys) {
/* 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 instanceof VNode) {
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 (
obj,
key,
val,
customSetter,
shallow
) {
var dep = new Dep(); var property = Object.getOwnPropertyDescriptor(obj, key);
if (property && property.configurable === false) {
return
} // cater for pre-defined getter/setters
var getter = property && property.get;
var setter = property && property.set; var childOb = !shallow && 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 = !shallow && 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 (target, key, val) {
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val
}
if (hasOwn(target, key)) {
target[key] = val;
return val
}
var ob = (target).__ob__;
if (target._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 val
}
if (!ob) {
target[key] = val;
return val
}
defineReactive(ob.value, key, val);
ob.dep.notify();
return val
} /**
* Delete a property and trigger change if necessary.
*/
function del (target, key) {
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.splice(key, 1);
return
}
var ob = (target).__ob__;
if (target._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(target, key)) {
return
}
delete target[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);
}
}
} /* */
vuejs源码摘抄(二)的更多相关文章
- vuejs源码摘抄
		订阅功能的部分实现代码如下: /* */ var uid = 0; /** * A dep is an observable that can have multiple * directives s ... 
- vueJs 源码解析 (三) 具体代码
		vueJs 源码解析 (三) 具体代码 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那么今天我们就从这三 ... 
- VueJs 源码解析 (四) initRender.Js
		vueJs 源码解析 (四) initRender.Js 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那 ... 
- Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题
		4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ... 
- Netty 源码(二)NioEventLoop 之 Channel 注册
		Netty 源码(二)NioEventLoop 之 Channel 注册 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 一 ... 
- 框架-springmvc源码分析(二)
		框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ... 
- Zookeeper 源码(二)序列化组件 Jute
		Zookeeper 源码(二)序列化组件 Jute 一.序列化组件 Jute 对于一个网络通信,首先需要解决的就是对数据的序列化和反序列化处理,在 ZooKeeper 中,使用了Jute 这一序列化组 ... 
- 一点一点看JDK源码(二)java.util.List
		一点一点看JDK源码(二)java.util.List liuyuhang原创,未经允许进制转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 List译为表,一览表, ... 
- Tomcat源码分析二:先看看Tomcat的整体架构
		Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ... 
随机推荐
- centos虚拟机设置静态ip
			1.虚拟机网络配置设置为桥接模式 2.设置配置文件: vi /etc/sysconfig/network-scripts/ifcfg-ens33 DEVICE=ens33 HWADDR=:0c::c3 ... 
- Convert DataTable to List<T> where Class of List is Dynamic
			using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Da ... 
- 建立链表的虚拟头结点 203 Remove Linked List Element,82,147,148,237
			该逻辑对于删除第一个元素不适用. 这样的代码不优美 /** * Definition for singly-linked list. * struct ListNode { * int val; * ... 
- 求一个区间里的一个x,这个x与这区间里面的所有数都互质
			链接:https://ac.nowcoder.com/acm/contest/301/H来源:牛客网 题描述 小乐乐上了一节数学课,数学老师讲的很好,小乐乐听的也如痴如醉. 小乐乐听了老师的讲解,知道 ... 
- HDU1501 简单DP
			dp[i][j]:用A的前i的字符和B的前j个字符能否组成i+j长度的合法C串 O(n^2)的方法有点糟糕 /*H E A D*/ char str1[maxn],str2[maxn],str3[ma ... 
- ZOJ - 3624
			当A连向C,B连向D时存在相交路径 #include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define ... 
- 【研究】ms17-010永恒之蓝漏洞复现
			1 永恒之蓝漏洞复现(ms17-010) 1.1 漏洞描述: Eternalblue通过TCP端口445和139来利用SMBv1和NBT中的远程代码执行漏洞,恶意代码会扫描开放44 ... 
- JENKINS安装及新建用户,权限配置
			JENKINS安装及新建用户,权限配置 1. 下载安装 jenkins 官网地址https://jenkins.io/index.html 下载地址https://jenkins.io/downloa ... 
- PIE SDK屏幕坐标和地图坐标转换
			1. 功能简介 屏幕坐标和地图坐标转换,就是字面意思,将电脑屏幕的坐标转换为带有空间信息的地图坐标,主要运用PIE SDK地图控件的ToMapPoint()方法,而地图坐标转换为设备坐标(屏幕),用的 ... 
- Echart 动态生成series数据
			要做成页面只传入数据,js生成图表,如下图 下面是js代码 var LineChart = function (ID, title, axisData,seriesData) { var myChar ... 
