事件对象
function EventEmit(){
// {
// "message":['事件1','事件2']
// }
this.callbacks={}
}
EventEmit.prototype.on=function(eventName,fn){
if(!this.callbacks[eventName]){
this.callbacks[eventName]=[]
}
this.callbacks[eventName].push(fn)
}
EventEmit.prototype.emit=function(eventName,fn){
if(!this.callbacks[eventName]){
return
}
this.callbacks[eventName].forEach(fn=>{
fn()
})
}
// 事件对象
// var e1=new EventEmit();
// // on订阅事件
// e1.on('message',function(){
// console.log('操作h1')
// })
// e1.on('message',function(){
// console.log('操作h2')
// })
// e1.on('message',function(){
// console.log('操作p')
// })
vue.js
;(function(){
function Vue(options){
var {el,data}=options
//根节点
var rootEl=document.querySelector(el);
var _data={}
var _events=new EventEmit();
// 数据观测
// 当data中的数据发生变化,发出事件通知,所以订阅了该事件的DOM都会得到更新
for(let key in data){
_data[key]=data[key]
Object.defineProperty(this,key,{
get(){
return _data[key]
},
set(val){
_data[key]=val
_events.emit(key)
}
})
}
// 递归解析模板,注册数据绑定事件
function compile(childNodes){
childNodes.forEach((node,index)=>{
switch(node.nodeType){
case 1:
// 处理input标签
if(node.nodeName==='INPUT'){
const vModel=node.attributes['v-model']
if(!vModel){
return
}
var dataKey=vModel.value.trim();
node.oninput=()=>{
this[dataKey]=node.value
}
}
// 标签节点继续递归调用
compile.call(this,node.childNodes)
break;
case 3:
var matches=/{{(.+)}}/.exec(node.textContent)
if(matches){
var dataKey=matches[1].trim()
node.textContent=_data[dataKey]
_events.on(dataKey,()=>{
node.textContent=_data[dataKey]
})
}
break;
}
})
}
compile.call(this,rootEl.childNodes)
}
window.Vue=Vue;
})()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
{{message}}
<p>{{message}}</p>
<div><p>{{message}}</p></div>
<input type="text" v-model="message">
</div>
<script src="js/eventemit.js"></script>
<script src="js/vue.js"></script>
<script>
{{}} v-model
var app=new Vue({
el:'#app',
data:{
message:'hello vue'
}
})
</script>
</body>
</html>