抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

最近几天一直在和同学们做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 });
}

这样我页面切换不仅能播放动画,还能干点别的。

饶过自己,不要堆屎山了

评论