##看了 OBKoro1大神的文章,受益匪浅.照着他的代码敲了几遍 一点一点的理解 才搞清楚 对于vue,有了更深的理解.谢谢 文章链接 juejin.im/post/5b2df5…
function myVue(options = {}){//默认空对象 防止不穿
this.$options = options;
this.$el = document.querySelector(options.el);
this._data = this.$options.data;
this._watcherTpl = {};//数据的观测池
this._observer(this.$options.data);
this.complie(this.$el)
}
muVue.prototype._observer = function(obj){
var _this = this;
Object.keys(obj).forEach( key =>{
_this._watcherTpl[key] ={
_directives:[]
}
let value = obj[key];
Object.defineProperty(this._data,key,{
configurable:true,//可以被删除
enumerable:true,//可以被枚举
get(){
return value
},
set(newVal){
if(value != newVal ){
value = newVal;
this._watcherTpl[key].directives.forEach(item=>{
item.update()
})
}
}
})
})
}
myVue.prototype._complie = function(el){
var _this = this,nodes = el.children;
for (var i=0,len = nodes.length;i<len;i++){
var node = nodes[i];
if(node.length){
_this._compile(node)
}
if(node.hasAttrubute('v-model')&&(node.tagName == 'INPUT'||node.tagName == 'TEXTERA')){
node.addEventListener('input',(function(){
var attVal = node.getAttribute('v-model'); // 获取v-model绑定的值
_this._watcherTpl[attVal]._directives.push(new Watcher( // 将dom替换成属性的数据并发布订阅 在set的时候更新数据
node,
_this,
attVal,
'value'
));
return function () {
_this._data[attVal] = nodes[key].value; // input值改变的时候 将新值赋给数据 触发set=>set触发watch 更新视图
}
})(i))
}
if (node.hasAttribute('v-bind')) { // v-bind指令
var attrVal = node.getAttribute('v-bind'); // 绑定的data
_this._watcherTpl[attrVal]._directives.push(new Watcher( // 将dom替换成属性的数据并发布订阅 在set的时候更新数据
node,
_this,
attrVal,
'innerHTML'
))
}
}
}
function Watcher(vm,el,attVal,val){
this.vm = vm;
this.el = el;
this.attVal = attVal;
this.val = val;
this.update()
}
Watcher.property.update = function(){
return this.el(this.val) = this.vm._data[this.attVal]
}
复制代码