最近几天一直在和同学们做h5移动端的网页,一直有考虑性能,直到现在还没有出现卡顿的现象,或许又不应该多花费心思在优化性能上。逻辑实现和优化性能之间需要权衡一下。
什么是发布订阅模式
发布订阅模式中,订阅者订阅消息,发布者触发更新消息,可以携带参数,还有删除订阅,将已订阅的消息从消息池中删除。
大体是这样,使用闭包封装message消息池
publisher发布消息,带上消息名字,可以传参
subscriber订阅消息,消息名,触发消息后的回调
removeSubscriber删除订阅,消息名,订阅时的回调函数,如果传入回调函数则只删除该订阅,否则把订阅者全清了。
const Obsevere = () => {
const _message = {};
return {
// 发布者
publisher: (type, args) => {},
// 订阅者
subscriber: (type, fn) => {},
// 删除订阅
removeSubscriber: (type, fn) => {},
};
};
实现:
const Obsevere = () => {
const _message = {};
return {
// 发布者
publisher: (type, args) => {
const toPush = _message[type];
toPush.forEach((e) => {
e.call(this, args);
});
},
// 订阅者
subscriber: (type, fn) => {
if (_message[type] == undefined) {
_message[type] = [fn];
} else {
_message[type].push(fn);
}
},
removeSubscriber: (type, fn) => {
const toRemove = _message[type];
if (_message[type] == undefined) {
return;
}
if (!fn) {
toRemove && (toRemove.length = 0);
return;
}
_message[type] = toRemove.reduce((acc, cur) => {
if (cur !== fn) {
return acc.concat(cur);
}
return acc;
}, toRemove[0]);
},
};
};
实际应用
发布订阅模式适合解决模块之间太过封闭,不方便通信的问题。
这次用来胡写一个在页面加载完毕后跳转画面的逻辑。
我选择先订阅一个HTMLload消息,在页面加载完毕后发布页面加载完毕的HTMLload消息,之后删掉该订阅
const o = Obsevere();
o.subscriber("HTMLload", (args) => {
// 页面加载完毕后,跳转到下一页
setTimeout(()=>{
index++;
app_box.style.top=(-index*app_height)+'px';
dealPageAnimation(index);
},200)
});
const timeid = setInterval(()=>{
const imgs = [...document.querySelectorAll("img")]
isCompleted = []
isCompleted = imgs.filter(Element=>Element.complete)
progress.innerText = ((isCompleted.length /29).toFixed(2)*100 +"%")
if(isCompleted.length===29){
// 此时页面加载完毕,发布HTMLload消息
o.publisher("HTMLload",true);
o.removeSubscriber("HTMLload");
clearInterval(timeid);
}
},200)
写的真好,自我评判一下,解决了代码都糊在一起后的臃肿问题,没了。
然后我想在页面跳转之后加上发布订阅,这样就可以在页面跳转之后管理事件就方便多了
大概是这样:
const pageArray = [page, page, page_2, page_3, page_4];
o.subscriber("pageChangeAnimation", ({ index }) => {
pageArray.forEach((elem) => elem.hide());
console.log(index, pageArray[index]);
pageArray[index]["show"]();
});
o.subscriber("pageChange", ({ index }) => {
o.publisher("pageChangeAnimation", { index });
});
function 在页面切换时(){
o.publisher("pageChange", { index });
}
这样我页面切换不仅能播放动画,还能干点别的。
饶过自己,不要堆屎山了