site-context-routes-handler.ts (SiteContextRoutesHandler)
三个依赖:
site context state 和 url 之间存在双向同步关系。
init
init() {
this.router = this.injector.get(Router);
this.location = this.injector.get(Location);
const routingParams = this.siteContextParams.getUrlEncodingParameters();
if (routingParams.length) {
this.setContextParamsFromRoute(this.location.path(true));
this.subscribeChanges(routingParams);
this.subscribeRouting();
}
}
上述代码,调用 getUrlEncodingParameters
获取参数列表:
然后从 this.location.path 得到当前浏览器地址栏里的 url,从 url /electronics-spa/en/USD
里提取出参数。
setContextParamsFromRoute
从 url 里解析参数,然后更新 site context state
解析出的参数是一个 JSON 对象:
根据参数名称,从 service map 里获取对应的 service 实例,然后调用 setValue 方法。
还是 facade 层的 setActive 方法:
最后在 reducer 里返回一个新的状态(有限状态自动机):
注意 callstack:
subscribeChanges
site context 发生变化之后,我们需要采用编程的方式,更新浏览器地址栏里的 url.
例子:当我从 language 下拉菜单里将语言从英语更改到中文时,断点立即触发:
此时 router url 里已经出现了 zh,这个值是什么时候写入的?
这行代码 this.location.replaceState(serialized);
单步执行之后,地址栏立即出现了zh:
语言发生变化之后,如何同步到浏览器地址栏的 url 字段?
切换成中文后,this.router.url 片段里,已经出现了 zh
,这是一个 get 实现:
调试器显示,这个 get 的执行根本还没结束:
上图是 Angular 框架代码,url 是通过 this.serializeUrl(this.currentUrlTree)
动态计算出来的。
router 的 urlSerializer 是我们动态注入进去的:
这里就开始执行我们自己的业务逻辑了:
params 参数为空:
segment,query 和 fragment 全部为空:
然后再从 urlEncodingParameters 里依次将 baseSite,language 和 currency 最新的参数值读取出来:
既然传进来的 params 里没有数据,就调用 SiteContextParamsService 读取参数值:
现在调用的就是 services 文件夹下的实现,之前已经了解过了:
从 service map 里读取数据:
这里读取的是最新的 zh 值:
所以 router 最后的值进行了更新:electronics-spa/zh/USD/