for(var i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i], obj[keys[i]]);
}
};
function defineReactive(obj, key, val) {
var dep = new Dep();
var property = Object.getOwnPropertyDescriptor(obj, key);
if(property && property.configurable === false) {
return;
}
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();
}
}
return value;
},
set: function reactiveSetter(newVal) {
var value = getter ? getter.call(obj) : val;
if(newVal === value) {
return;
}
if(setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
childOb = observe(newVal);
dep.notify();
}
});
}
function observe(value) {
if(!value || typeof value !== 'object') {
return;
}
return new Observer(value);
}
function Vue(options) {
var vm = this;
this._el = options.el;
var data = this._data = options.data;
var keys = Object.keys(data);
var i = keys.length;
while(i--) {
proxy(this, keys[i]);
}
observe(data);
var elem = document.getElementById(this._el);
elem.innerHTML = vm.message;
new Watcher(this, 'message', function() {
elem.innerHTML = vm.message;
});
}
function proxy(vm, key) {
Object.defineProperty(vm, key, {
configurable: true,
enumerable: true,
get: function proxyGetter() {
return vm._data[key];
},
set: function proxySetter(val) {
vm._data[key] = val;
}
});
}
return Vue;
})();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="vue.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/javascript">
var app = new Vue({
el: 'app',
data: {
message: 'aaaaaaaaaaaaa'
}
});
</script>
</body>
</html>参考资料:
vue 源码分析之如何实现 observer 和 watcher
vue早期源码学习系列之一:如何监听一个对象的变化










