Vue 源码与踩坑
2019-12-26 本文已影响0人
李霖弢
1. data属性为什么使用了_或$开头却会提示报错?
vue采用了defineProperty
实现数据驱动视图,此时数据均挂载在$data
或_data
上,要想让数据能直接被this
访问,还做了如下处理
// target是vue实例,key为_data,这样就能通过访问this.xxx = this._data.xxx了
function proxy (target, sourceKey, key) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
};
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val;
};
Object.defineProperty(target, key, sharedPropertyDefinition);
}
此时有如下检测,当属性以_
或$
开头时不会调用proxy方法,因此只能通过_data.属性名
或$data.属性名
访问
function initData (vm) {
var data = vm.$options.data;
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
if (!isPlainObject(data)) {
data = {};
process.env.NODE_ENV !== 'production' && warn(
'data functions should return an object:\n' +
'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
);
}
// proxy data on instance
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)) {
// 这边处理代理,所以isReserved处理了是否要进行代理
proxy(vm, "_data", key);
}
}
// observe data
observe(data, true /* asRootData */);
function isReserved (str) {
var c = (str + '').charCodeAt(0);
return c === 0x24 || c === 0x5F // 这边判断chartCode是否为_和$
}
}
2. 观察者模式 和 发布-订阅者模式
观察者模式
被观察者中记录注册到其的观察者,每当被观察者触发变化时,主动驱动观察者的方法
发布-订阅者模式
订阅者把自己想订阅的事件注册到调度中心,当发布者触发变化时,将事件推送给调度中心,调度中心找到订阅该事件的订阅者,并驱动其方法