<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
<script type="text/javascript">
var temObserable;
// 观察者
function Observer (){
this.observables = []
}
Observer.prototype.notify = function(){
for(var i=0;i<this.observables.length;i++){
this.observables[i].update()
}
}
Observer.prototype.subscribe = function(){
this.observables.push(temObserable)
}
//可观察对象 具备事件触发的能力
function Observable(node,propName,data){
this.$node = node;
this.$propName= propName;
this.$data = data;
}
Observable.prototype.update = function(){
if(this.$node.nodeType === 1){
this.$node.value = this.$data[this.$propName]
} else if(this.$node.nodeType === 3){
this.$node.nodeValue = this.$data[this.$propName]
}
}
// MVVM 是一个构造函数,接受一个options对象,存起来
function MVVM(options){
this.$el = options.el;
this.$options = options;
this.$data = options.data;
this.$template = options.template;
this.$$data = this.$data();//数据对象
//监视属性,遍历对象
this.init();
}
MVVM.prototype.init = function(){
this.defineReactive(this.$$data,this.$$data.text); //{text:'abc'}
this.compiler(this.$template,this.$$data)
};
MVVM.prototype.compiler = function(tempstr,data){
//将tempstr插入到app中
var box = document.querySelector(this.$el);
box.innerHTML = tempstr
//分析box 获取到其中的标记
var nodes = box.children[0].childNodes;
//正则匹配
var regexText = /.*\{\{(.*)\}\}.*/;
var regexV = /^v-(.*)$/
// var i=0;i<nodes.length;i++
for(var i = nodes.length-1;i>=0;i--){
//判断Nodetype ===3 文本标签,===1 input标签
var node= nodes[i]
if(node.nodeType === 3){
var result = regexText.exec(node.nodeValue);
if(result){
//获取结果与this.$$data匹配 this.$$data[XXX]
//触发获取
this.textMatch(result[1].trim(), node); //text
}
}else if(node.nodeType === 1){
//获取元素的属性名称
var nodeAttrs = node.attributes;
for(var j=0;j<nodeAttrs.length;j++){
console.log(nodeAttrs[j])
var attr = nodeAttrs[j];
var result = regexV.exec(attr.name)
if(result){
console.log(attr.name,attr.value,"被匹配了",result)
this.redirective[result[1]](attr.value, node, this.$$data)
}
}
}
}
}
MVVM.prototype.redirective = {
model:function(propName, node, data){
temObserable = new Observable(node,propName,data)
//给元素添加事件和给一个初始值
node.value = data[propName];
node.addEventListener('input',function(e){
data[propName] = e.target.value
})
}
}
MVVM.prototype.textMatch = function(propName, node){
//1创建存储信息的行为 可观察对象
//2将其挂载全局
//3触发get函数,并从全局中取出1
temObserable = new Observable(node,propName,this.$$data)
node.nodeValue = this.$$data[propName]
}
MVVM.prototype.defineReactive = function(obj,value){
for(var key in obj){
//创建观察者
var Observers = new Observer()
Object.defineProperty(obj,key,{
set:function(v){
//更新观察者中的所有可观察对象中的节点数据
value = v;
console.log('set触发')
Observers.notify()
},
get:function(){
//为节点初始化的时候触发,将当前的节点关联上可观察对象,并加入到观察者中
console.log('get触发')
if(temObserable){
Observers.subscribe();
temObserable = null
}
return value
}
})
}
}
var vm = new MVVM({
el:"#app",
data(){
return {
text:"abc"
}
},
template:"<div><input type='text' v-model='text'/>{{text}}</div>"
})
</script>
网友评论