前言
回首前章也是有写过vue
双向绑定的,基于Object.defineProperty()
,那是自己一句一句代码撸出来的,查看了各种文章 去看看
然后 :
一场公开课被虐到无地自容 , 大佬的 proxy
版本,话不多说 ,直接上代码,分享给大家欣赏一下 。
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>响应式数据</title>
<script>
class vue extends EventTarget{
constructor(option){
super();
this.option = option;
this.$data = this.option.data;
this.$el = document.querySelector(this.option.el);
this.observe(this.$data);
this.compileNode(this.$el);
}
observe(data){
let _this = this;
this.$data = new Proxy(data,{
set(target,prop,newValue){
let event = new CustomEvent(prop,{
detail:newValue
});
_this.dispatchEvent(event);
return Reflect.set(...arguments);
}
});
}
compileNode(el){
let child = el.childNodes;
[...child].forEach(node=>{
if(node.nodeType === 3){
// console.log('这是一个文本节点');
let text = node.textContent;
let reg = /\{\{\s*([^\s\{\}]+)\s*\}\}/g;
if(reg.test(text)){
let $1 = RegExp.$1;
this.$data[$1] && (node.textContent = text.replace(reg,this.$data[$1]));
this.addEventListener($1,e=>{
node.textContent = text.replace(reg,e.detail)
});
}
}else if(node.nodeType === 1){
let attr = node.attributes;
if(attr.hasOwnProperty('v-model')){
let keyName = attr['v-model'].nodeValue;
node.value = this.$data[keyName];
node.addEventListener('input',e=>{
this.$data[keyName] = node.value;
})
}
this.compileNode(node);
}
})
}
}
</script>
</head>
<body>
<div id="app">
{{name}}
<div>{{message}}</div>
{{message}} <input v-model="test"> {{test}}
</div>
<script>
let vm = new vue({
el:'#app',
data:{
name:'hisen',
message:'测试数据',
test:'请输入'
}
})
</script>
</body>
</html>