import Vue from '../modules/vue'
var vm = new Vue({
el:'#app',
template: `
<span>{{a}}</span>
<span>+</span>
<span>{{b}}</span>
<span>=</span>
<span>{{total}}</span>
`,
data(){
return {
a:1,
b:2,
}
},
computed:{
total(){
console.log('computed total');
return this.a + this.b
},
total:{
get:function(){
console.log('computed total');
return this.a + this.b
}
}
}
});
console.log(vm);
console.log(vm.total);
console.log(vm.total);
console.log(vm.total);
console.log(vm.total);
vm.a = 100;
console.log(vm.total);
console.log(vm.total);
console.log(vm.total);
console.log(vm.total);
var Vue = (function(){
var computedData = {},
reg_var = /\{\{(.+?)\}\}/g,
dataPool = {};
var Vue = function(options){
this.$el = document.querySelector(options.el);
this.$data = options.data();
this._init(this, options.computed,options.template);
}
Vue.prototype._init = function(vm,computed,template){
dataReactive(vm);
computedReactive(vm,computed);
render(vm,template);
}
function render(vm,template){
var container = document.createElement('div');
var _el = vm.$el;
container.innerHTML = template;
var domTree = _compileTemplate(vm,container);
_el.appendChild(domTree);
}
function updata(vm,key){
dataPool[key] && (dataPool[key].textContent = vm[key]);
}
function _compileTemplate(vm,container){
var allNodes = container.getElementsByTagName('*');
for(var i=0;i<allNodes.length;i++){
var nodeItem = allNodes[i];
var matched = nodeItem.textContent.match(reg_var);
if(matched){
nodeItem.textContent = nodeItem.textContent.replace(reg_var,function(node,key){
dataPool[key.trim()] = nodeItem;
return vm[key.trim()];
});
}
}
return container;
}
function dataReactive(vm){
var _data = vm.$data;
for(var key in _data){
(function(key){
Object.defineProperty(vm, key, {
get: function(){
return _data[key];
},
set: function(newValue){
_data[key] = newValue;
updata(vm,key)
updataComputeData(vm,key,function(vm,key){
updata(vm,key)
})
}
})
})(key);
}
}
function computedReactive(vm,computed){
_initComputedData(vm,computed);
for (const key in computedData) {
(function(key){
Object.defineProperty(vm, key, {
get: function(){
return computedData[key].value;
},
set: function(newValue){
computedData[key].value = newValue;
}
})
})(key);
}
}
function _initComputedData(vm,computed){
for (const key in computed) {
var descriptor = Object.getOwnPropertyDescriptor(computed,key),
descriptorFn = descriptor.value.get?descriptor.value.get:descriptor.value;
computedData[key] = {};
computedData[key].value=descriptorFn.call(vm);
computedData[key].get = descriptorFn.bind(vm);
computedData[key].dep = _collectDep(descriptorFn);
}
}
function _collectDep(fn){
var _collection = fn.toString().match(/this\.\w+/g);
if(_collection.length >0){
for(var i=0;i<_collection.length;i++){
_collection[i] = _collection[i].replace('this.','');
}
}
return _collection;
}
function updataComputeData(vm,key,updata){
var _dep = [];
for (const _key in computedData) {
_dep = computedData[_key].dep;
console.log('_dep',_dep,key);
for (let i = 0; i < _dep.length; i++) {
if(_dep[i] == key){
vm[_key] = computedData[_key].get();
updata(vm,_key)
}
}
}
}
return Vue;
})();
export default Vue;