一、html部分
<div id="box1">
{{ name }}
</div>
<div id="box2">
{{name}}
</div>
<div id="box3">
{{name}}
</div>
<div id="box4">
{{age}}
</div>
<div id="box5">
{{order}}
</div>
<div id="box6">
{{ order}}
</div>
<div id="box7" >
未订阅
</div>
<div id="box8">
未订阅
</div>
<div id = "updatedom">已更新dom:</div>
<button id="btn">改变数据</button>
二、js部分
/* 属性侦听 */
let proxy= new Proxy({
name:"Rony",
age:"18",
order:6666
}, {
set: function (target, propKey, value, receiver) {
dep.update(value,propKey);
}
});
/* 订阅者列表 */
let dep ={
listenerArr:[],//订阅者列表
update:function(value,key){
let updateDomLength=0;
for(let i in this.listenerArr){
if(this.listenerArr[i].type==key){
updateDomLength+=1;//需要更新的dom数量
this.listenerArr[i].changeVal(value);
}
document.getElementById("updatedom").innerText="已更新dom:"+updateDomLength;
}
}
}
/* 订阅class */
class Watcher{
constructor(el,type){
this.el = document.getElementById(el);
let patt =/{{(.*?)}}/;
if(patt.test(this.el.innerText)){
this.type = this.el.innerText.match(patt)[1].trim();
this.el.innerText = "已经订阅";
dep.listenerArr.push(this);
}
}
changeVal(value){
this.el.innerHTML =this.type+":"+value;
}
}
/* 订阅实例 */
let dep1 = new Watcher("box1");
let dep2 = new Watcher("box2");
let dep3 = new Watcher("box3");
let dep4 = new Watcher("box4");
let dep5 = new Watcher("box5");
let dep6 = new Watcher("box6");
let dep7 = new Watcher("box7");
let dep8 = new Watcher("box8");
/* 模拟改变数据 */
document.getElementById("btn").addEventListener("click",function(){
let random = Math.random();
if(random<0.3){
proxy.name=random;
}else if(random>0.3&&random<0.6){
proxy.age =random;
}else{
proxy.order =random;
}
})
1、每创建一个Watcher实例,会把实例添加到dep对象的listenerArr数组中,即订阅者列表;
2、当数据更新时触发dep对象的update方法,该方法会遍历订阅者列表并过滤符合字段更新条件的订阅者,使订阅者调用自身的changeVal方法,触发dom响应式更新