vue源码解析data与watcher
以一份简单的例子说明:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src='node_modules/vue/dist/vue.js' type='text/javascript'></script>
</head>
<body>
<div id='app'></div>
<script type='text/javascript'>
var vueIns=new Vue({
data(){
return {
aaa:1,
bbb:2
}
},
created(){
this.aaa =3
},
methods:{
confirm(){
this.bbb=333
}
},
template:'<div><h1>{{aaa}}</h1><h2>{{bbb}}</h2></div>'
}).$mount('#app')
console.log(vueIns)
</script>
</body>
</html>
Vue对象中的data对象
Observer.prototype.walk = function walk (obj) { var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { defineReactive$$1(obj, keys[i]); } }; /** * Define a reactive property on an Object. */ function defineReactive$$1 ( 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; if ((!getter || setter) && arguments.length === 2) { val = obj[key]; } 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 (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(); } }); }
将_data的数据进行遍历defineProperty
得到:vm.aaa的形式
_data:
aaa: 3
bbb: 2
__ob__: Observer {value: {…}, dep: Dep, vmCount: 1}
get aaa: ƒ reactiveGetter()
set aaa: ƒ reactiveSetter(newVal)
get bbb: ƒ reactiveGetter()
set bbb: ƒ reactiveSetter(newVal)
代理:proxy方法
proxy(vm, "_data", key);
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);
}
得到
aaa: 3 bbb: 2 __proto__: Object get aaa: ƒ proxyGetter() set aaa: ƒ proxySetter(val) get bbb: ƒ proxyGetter() set bbb: ƒ proxySetter(val)
数据监控执行
initWatch
function initWatch (vm, watch) {
for (var key in watch) {
var handler = watch[key];
if (Array.isArray(handler)) {
for (var i = 0; i < handler.length; i++) {
createWatcher(vm, key, handler[i]);
}
} else {
createWatcher(vm, key, handler);
}
}
}
function createWatcher (
vm,
expOrFn,
handler,
options
) {
if (isPlainObject(handler)) {
options = handler;
handler = handler.handler;
}
if (typeof handler === 'string') {
handler = vm[handler];
}
return vm.$watch(expOrFn, handler, options)
}
Vue.prototype.$watch = function (
expOrFn,
cb,
options
) {
var vm = this;
if (isPlainObject(cb)) {
return createWatcher(vm, expOrFn, cb, options)
}
options = options || {};
options.user = true;
var watcher = new Watcher(vm, expOrFn, cb, options);
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();
}
};
}


浙公网安备 33010602011771号