VUE逐点突破系列 -- VUE响应式原理剖析
VUE逐点突破系列 – VUE响应式原理剖析手写实现简单的响应式双向绑定<html><head><meta charset="UTF-8"/><title>vue</title><script src="./vue.js"></script></head></html><body>
·
VUE逐点突破系列 – VUE响应式原理剖析
手写实现简单的响应式双向绑定
<html>
<head>
<meta charset="UTF-8"/>
<title>vue</title>
<script src="./vue.js"></script>
</head>
</html>
<body>
<div id="app">
{{name}}
<div>{{message}}</div>
<input v-model='test'/>
{{test}}
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
name: 'lili',
message: '测试数据',
test: ''
}
})
</script>
下面是html文件中引用的vue.js文件
继承类 EventTarget
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){
// 文字节点
let text = node.textContent;
// 通过正则匹配两侧为{{}}且忽略中间空格的代码
let reg = /\{\{\s*([^\s\{\}]+)\s*\}\}/
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;
// 元素节点含有v-model属性
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)
}
})
}
}
更多推荐
已为社区贡献5条内容
所有评论(0)