逻辑 -> 数据 <—>视图
/**
* 1. 数据 -> 响应式数据 Object.defineProperty Proxy
* 2. input -> input/keyup -> 事件处理函数的绑定 -> 改变数据
* 3. 相关的DOM & 数据 => 绑定在一起
* 操作数据的某个属性 -> 对应DOM就改变
* {
* 'name': [span节点]
* }
*
*
*
*/
const reg_var = /\{\{(.*?)\}\}/;
// eslint-disable-next-line
class MVVM {
constructor(el, data){
this.el = document.querySelector(el);
// this._data = data;
this.data = data;
this.domPool = {};//dom池
this.init();
}
init(){
this.initData();
this.initDom();
}
initData(){
const _this = this;
// this.data = {};
// for(const key in this._data){
// if(typeof key === 'object'){
// //递归
// }
// Object.defineProperty(this.data, key, {
// get(){
// console.log("获取数据: ", key, _this._data[key]);
// return _this._data[key];
// },
// set(newValue){
// if(newValue===_this._data[key]){
// return;
// }
// console.log("设置数据: ", key, _this._data[key]);
// _this.domPool[key].innerText = newValue;
// _this._data[key] = newValue;
// }
// });
// }
//Proxy写法
this.data = new Proxy(this.data, {
get(target, key){
return Reflect.get(target, key);
},
set(target, key, value){
_this.domPool[key].innerText = value;
return Reflect.set(target, key, value);
}
})
}
initDom(){
this.bindDom(this.el);//这应该先执行
console.log("看看dom池子:",this.domPool);
this.bindInput(this.el);
}
//数据与DOM节点绑定--解析出{{name}}绑定到对应节点上
bindDom(el){
if(!el){
return;
}
const childNodes = el.childNodes;
// console.log("el.childNodes: ", childNodes);
childNodes.forEach(item => {
//如果是文本节点
if(item.nodeType===3){
const _value = item.nodeValue;
// console.log(_value);
if(_value.trim().length){
let _isValid = reg_var.test(_value);//捕获组&懒惰模式
if(_isValid){
const _key = _value.match(reg_var)[1].trim();
console.log("匹配到的属性:", _key);
this.domPool[_key] = item.parentNode;//其实应该是个set集合,这里简化为1v1了
//再设置DOM
item.parentNode.innerText = this.data[_key] || undefined;
}
}
}
item.childNodes && this.bindDom(item);//递归
});
}
//input--绑定事件处理函数
bindInput(el){
if(!el){
return;
}
const _allInputs = el.querySelectorAll('input');
_allInputs.forEach(input=>{
const _vModel = input.getAttribute('v-model');
if(_vModel){
input.addEventListener('keyup', this.handleInput.bind(this, _vModel, input));
}
})
}
handleInput(key, input){
const _value = input.value;
this.data[key] = _value;
}
setData(key, value){
this.data[key] = value;
}
}