initInjections(vm); // resolve injections before data/props
function initInjections (vm) {
var result = resolveInject(vm.$options.inject, vm); //返回 key value 对象
if (result) {
toggleObserving(false);
//关闭 observe ,不允许对 Inject 中的值赋值,所以 injections不需要observe
Object.keys(result).forEach(function (key) {
/* istanbul ignore else */
{
defineReactive$$1(vm, key, result[key], function () {
warn(
"Avoid mutating an injected value directly since the changes will be " +
"overwritten whenever the provided component re-renders. " +
"injection being mutated: \"" + key + "\"",
vm
);
});
}
});
toggleObserving(true); //开启 observe
}
}
resolveInject 方法主要是将provide和inject整合在一起,并返回最终的结果
for(var i = 0; i < keys.length; i++)
...
while (source) { //遍历vm,从当前vm开始,一层层往上,找到有‘key’的provide的值
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey];
break //有值则跳出当前的for循环
}
source = source.$parent;
}
如果没有找到会用 inject 的 default 方法
if (!source) {
if ('default' in inject[key]) {
var provideDefault = inject[key].default;
result[key] = typeof provideDefault === 'function'
? provideDefault.call(vm)
: provideDefault;
} else {
warn(("Injection \"" + key + "\" not found"), vm);
}
}
return result //返回最终的结果
initState 初始化了5个属性
function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
if (opts.props) { initProps(vm, opts.props); }
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
if (opts.computed) { initComputed(vm, opts.computed); }
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch);
}
}
initProps (和 inject 一样不允许修改,都是单向数据流)
var loop = function ( key ) {
keys.push(key);
var value = validateProp(key, propsOptions, propsData, vm);
/* istanbul ignore else */
{
var hyphenatedKey = hyphenate(key);
if (isReservedAttribute(hyphenatedKey) ||
config.isReservedAttr(hyphenatedKey)) {
warn(
("\"" + hyphenatedKey + "\" is a reserved attribute and cannot be used as component prop."),
vm
);
} // prop不能是保留的属性
......
}
// static props are already proxied on the component's prototype
// during Vue.extend(). We only need to proxy props defined at
// instantiation here.
if (!(key in vm)) {
proxy(vm, "_props", key); //proxy代理props
}
};
initMethods
vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
//methods用bind方法指向this
var bind = Function.prototype.bind
? nativeBind
: polyfillBind;
function polyfillBind (fn, ctx) {
function boundFn (a) {
var l = arguments.length;
return l
? l > 1
? fn.apply(ctx, arguments)
: fn.call(ctx, a)
: fn.call(ctx)
}
boundFn._length = fn.length;
return boundFn
}
function nativeBind (fn, ctx) {
return fn.bind(ctx)
}
initData
首先会判断data是函数还是对象的写法然后取值
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
这里会判断 data 不能和 props、methods 中的 key 重名
var keys = Object.keys(data);
var props = vm.$options.props;
var methods = vm.$options.methods;
var i = keys.length;
while (i--) {
var key = keys[i];
if (process.env.NODE_ENV !== 'production') {
if (methods && hasOwn(methods, key)) {
warn(
("Method \"" + key + "\" has already been defined as a data property."),
vm
);
}
}
if (props && hasOwn(props, key)) {
process.env.NODE_ENV !== 'production' && warn(
"The data property \"" + key + "\" is already declared as a prop. " +
"Use prop default value instead.",
vm
);
} else if (!isReserved(key)) {
proxy(vm, "_data", key);
}
}
判断没有重名之后开始 observe data
...
observe(data, true /* asRootData */);
...
function observe (value, asRootData) {
if (!isObject(value) || value instanceof VNode) {
return
}
var ob;
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__; //判断是否有__ob__属性并且__ob__是Observer函数的实例
} else if (
shouldObserve && //开关
!isServerRendering() && // 服务端渲染
(Array.isArray(value) || isPlainObject(value)) && // 数组或对象(不是null)
Object.isExtensible(value) && //value可扩展
!value._isVue //没有_isVue属性
) {
ob = new Observer(value); //调用Observer方法
}
if (asRootData && ob) {
ob.vmCount++;
}
return ob
}
Observer 方法
var Observer = function Observer (value) {
this.value = value;
this.dep = new Dep();
this.vmCount = 0;
def(value, '__ob__', this); //调用def函数给value增加__ob__属性
if (Array.isArray(value)) { //数组
//两个方法都是重新定义数组的,对value数组的方法增加劫持
if (hasProto) {
// 如果浏览器支持__proto__属性的,将value的__proto__指向arrayMethods
protoAugment(value, arrayMethods);
} else {
//不支持的话调用def函数将arrayMethods中的几个方法替换value原生的方法
copyAugment(value, arrayMethods, arrayKeys);
}
this.observeArray(value); //observe数组中的每一项
} else { //对象
this.walk(value); //对value对象中的每个可枚举key进行双向绑定,walk方法中用到了defineReactive$$1
}
};
protoAugment 和 copyAugment
/**
* Augment a target Object or Array by intercepting
* the prototype chain using __proto__
*/
function protoAugment (target, src) {
/* eslint-disable no-proto */
target.__proto__ = src;
/* eslint-enable no-proto */
}
/**
* Augment a 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]);
}
}
defineReactive?1函数
function defineReactive$$1 (
obj,
key,
val,
customSetter,
shallow
) {
var dep = new Dep();
var property = Object.getOwnPropertyDescriptor(obj, key);
if (property && property.configurable === false) {
//Object.freeze(obj) 可以去除双向绑定
return
}
// cater for pre-defined getter/setters
var getter = property && property.get;
var setter = property && property.set;
if ((!getter || setter) && arguments.length === 2) {
val = obj[key];
} // 对property进行取值(如果没有设置了get,set方法 Object.defineProperty...)
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) { //在Watcher的get方法中会给Dep.target赋值,是一个Watcher函数的实例
dep.depend(); // Watcher实例收集依赖
if (childOb) { //如果有子对象
childOb.dep.depend(); // watcher实例收集子对象依赖
if (Array.isArray(value)) { //判断是否为数组
dependArray(value); // watcher实例收集数组中的每个元素
}
}
}
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val;
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter();
}
// #7981: for accessor properties without setter
if (getter && !setter) { return }
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
childOb = !shallow && observe(newVal);
dep.notify(); //触发notify 视图更新
}
});
}
initComputed
生成一个computed 的watcher(观察者)
...
if (!isSSR) {
// create internal watcher for the computed property.
watchers[key] = new Watcher(
vm,
getter || noop,
noop,
computedWatcherOptions
);
}
...
defineComputed(vm, key, userDef);
//这里用Object.defineProperty去定义computed上的key
initWatch
watch对象里面的方法都是用 $watch 方法来初始化的
Vue.prototype.$watch = function (
expOrFn,
cb,
options
) {
...
var watcher = new Watcher(vm, expOrFn, cb, options); //生成对应的watcher
if (options.immediate) {
try {
cb.call(vm, watcher.value);
} catch (error) {
handleError(error, vm, ("callback for immediate watcher \"" + (watcher.expression) + "\""));
}
}
return function unwatchFn () { //返回一个可以取消观察的函数
watcher.teardown();
}
};
initProvide
function initProvide (vm) {
var provide = vm.$options.provide;
if (provide) {
vm._provided = typeof provide === 'function' //判断是函数还是对象,取值
? provide.call(vm)
: provide;
}
}
beforeCreate 到 created 主要是三个方法: initInjections, initState, initProvide, 并且inject必须在data之前,因为data中可以访问到this.[inject中的属性], provide可以访问data中的值,所以要在data之后初始化