123.路由重写-reroute

源码 2024-9-6 17:36:03 32 0 来自 中国
reroute 方法,没有调用start时举行加载app,调用loadApps方法,loadApps中准备加载应用,准备完毕后注册自界说事故callAllEventListeners
function reroute() {      if (isStarted()) {        appChangeUnderway = true;        appsThatChanged = appsToUnload.concat(          appsToLoad,          appsToUnmount,          appsToMount        );        return performAppChanges();      } else {        appsThatChanged = appsToLoad;        return loadApps();      }      function loadApps() {        return Promise.resolve().then(function () {          var loadPromises = appsToLoad.map(toLoadPromise);          return (            Promise.all(loadPromises)              .then(callAllEventListeners)              .then(function () {                return [];              })              .catch(function (err) {                callAllEventListeners();                throw err;              })          );        });      }}callAllEventListeners方法,遍历每个应用,给每个应用都添加callCapturedEventListeners事故监听,这边是操纵的备份对象不会对欣赏器中的事故举行重写。
  function callAllEventListeners() {    pendingPromises.forEach(function (pendingPromise) {      callCapturedEventListeners(pendingPromise.eventArguments);    });    callCapturedEventListeners(eventArguments);  }callCapturedEventListeners方法,遍历快照中重写的方法,之后监听到"hashchange", "popstate"时就会走我们自己界说的方法逻辑。
var routingEventsListeningTo = ["hashchange", "popstate"];function callCapturedEventListeners(eventArguments) {  var _this = this;  if (eventArguments) {    var eventType = eventArguments[0].type;    if (routingEventsListeningTo.indexOf(eventType) >= 0) {      capturedEventListeners[eventType].forEach(function (listener) {        try {          // The error thrown by application event listener should not break single-spa down.          // Just like https://github.com/single-spa/single-spa/blob/85f5042dff960e40936f3a5069d56fc9477fac04/src/navigation/reroute.js#L140-L146 did          listener.apply(_this, eventArguments);        } catch (e) {          setTimeout(function () {            throw e;          });        }      });    }  }}这个流程完毕之后,主应用调用了start方法后,就开始走performAppChanges相干逻辑。上篇文章有讲到过,重要是通过控制状态来到达激活和切换子应用的效果。
路由切换的时间怎么举行微应用加载的?
实现原理:通过监听和重写欣赏器的hashchange、popstate、pushState和replaceState的方法
下面这段代码是默认实行的,阐明一开始就对欣赏器中的方法举行了注册和重写,hash模式的代码会重写hashchange方法,当使用history模式时,pushState和 replaceState事故被触发时不会触发 popstate事故,只有back、forward、go才可以触发。
pushState:只会向汗青堆栈内里添加一个状态,不会更新页面,传了url差异源时会报错,不传则将其设置为当前文档的url。
replaceState:修改当前汗青记载实体 ,同上,传了url差异源时会报错,不传则将其设置为当前文档的url。
//判断是否在欣赏器环境if (isInBrowser) {  window.addEventListener("hashchange", urlReroute);  window.addEventListener("popstate", urlReroute);  // 不要直接操纵原有方法,在copy的方法上操纵  var originalAddEventListener = window.addEventListener;  var originalRemoveEventListener = window.removeEventListener;//重写pushState方法  window.history.pushState = patchedUpdateState(    window.history.pushState,    "pushState"  );    //重写replaceState方法  window.history.replaceState = patchedUpdateState(    window.history.replaceState,    "replaceState"  );}patchedUpdateState,记载跳转前和跳转后的url,假如urlBefore和urlAfter差异的时间才会重写路由,否则就只要举行pushState和replaceState操纵就会调用。
只有子应用启动了之后才手动触发popState事故,由于在没有启动子应用之前就可以使用默认的路由事故了。
dispatchEvent即为派发事故,现实就是我们在开始时监听了popstate事故,回调函数即reroute,因此pushstate和replacestate实行reroute的本质上是通过popstate来触发route的
function patchedUpdateState(updateState, methodName) {  return function () {      //性能优化,只有当当前页面和要跳转的页面不一样时才创建createPopStateEvent      //获取跳转前的url    var urlBefore = window.location.href;    var result = updateState.apply(this, arguments);      //获取跳转后的url    var urlAfter = window.location.href;    if (!urlRerouteOnly || urlBefore !== urlAfter) {      if (isStarted()) {        window.dispatchEvent(          createPopStateEvent(window.history.state, methodName)        );      } else {        reroute([]);      }    }    return result;  };}createPopStateEvent方法,将重写后的popstate返回
function createPopStateEvent(state, originalMethodName) {  var evt;  try {    evt = new PopStateEvent("popstate", {      state: state,    });  } catch (err) {    evt = document.createEvent("opStateEvent");    evt.initPopStateEvent("popstate", false, false, state);  }  evt.singleSpa = true;  evt.singleSpaTrigger = originalMethodName;  return evt;}为什么要重写pushState和 replaceState方法?
这篇文章对这个标题的表明我以为是最公道的
除了在微前端框架中须要监听对应的导航事故外,在微前端框架外部我们也可以通过 addEventListener 的方式来注册 hashchange 和 popstate 事故,那么如许一来导航事故就会有多个,为了在实现对导航事故的控制,到达路由变革时对应的子应用可以或许精确的 卸载挂载,须要对 addEventListener 注册的 hashchange 和 popstate 举行拦截,并将对应的事故给存储起来,便于后续在特定的时间可以或许实现手动触发。
发现在挂载和卸载阶段都调用了callAllEventListeners方法,而callAllEventListeners又调用了callCapturedEventListeners方法,callCapturedEventListeners方法中是对"hashchange", "popstate"挨个举行手动调用。
这证实白加载子应用时通过reroute和路由控制不停地在加载和切换子应用。
callCapturedEventListeners方法源码参考上面
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-23 20:00, Processed in 0.146992 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表