都9102年了,笔者所在的公司的主要项目仍是用AngularJS 1.6这种史诗的框架进行开发的。另外因为历史的缘由,代码的凌乱程度早已超越想象。为此,笔者决定痛下决心把整个项目重构了一遍...今后踏上了Angular升(跳)级(坑)之路。html
AngularJS的例子项目angular-phonecathtml5
在上篇文章中,项目已经基本能正常运行了。但其实在项目里还有许多未解决的问题,其中包括:git
在项目中使用的是双路由的策略。即ng1(AngularJS)、ngx(Angular)各自的页面其实仍是用相应的路由进行管理的。所以,两个路由间须要一个“桥梁”进行通讯,让他们彼此间的数据进行同步,而这个“桥梁”官方早已为咱们提供好了,那就是setUpLocationSync
。
在使用“桥梁”进行通讯前,还需对路由进行改造,让它们更符合咱们项目的需求。github
在ngx的路由器中,默认使用的是history模式的路由形式。但ng1路由器中默认使用的则是hash模式的路由形式。所以,咱们首先要作的,就是要让它们的模式设置为一致。
hash和history模式各有利弊,它们之间的区别能够参考附录:LocationStrategy 以及浏览器 URL 样式。笔者更推荐使用history模式,由于他更符合浏览器的URL风格。
下面介绍一下它们各自的设置方法:gulp
若是使用history模式,那么你主要修改ng1的路由器配置。bootstrap
angular.
module('phonecatApp').
config(['$routeProvider','$locationProvider',
function config($routeProvider,$locationProvider) {
$locationProvider.html5Mode(true) // 设置为html5 mode
}
]);
复制代码
若是使用hash模式,那么你主要修改的就是Angular的路由配置。浏览器
@NgModule({
imports: [RouterModule.forRoot(routes,{
useHash: true
})]
})
export class AppRoutingModule {
}
复制代码
在ng1.6你可能使用的是hash-bang模式,或者在ng1中设置了任何的前缀,你须要将其前缀去掉。bash
angular.
module('phonecatApp').
config(['$locationProvider',
function config($locationProvider) {
$locationProvider.hashPrefix('')
}
]);
复制代码
在实际的项目中,有些页面是基于ng1写的,有些页面是基于ngx写的。在多数状况下,咱们天然是但愿能各自显示页面相互不被打扰。所以,咱们须要作一个“凹槽路由”让它们能自由切换。(文段参考 2)
那么。凹槽路由到底是什么?简单而言就是“空页面”。在显示ng1的页面时,ngx部分显示一个空白的页面不就能够了?同理的,在显示ngx的页面,咱们进行相应的操做。
在ng1中实现比较简单:app
angular.
module('phonecatApp').
config(['$routeProvider',
function config($routeProvider) {
$routeProvider.
..., // 此处省略其余路由
otherwise({
template: ''
});
}
]);
复制代码
在ngx中,你须要添加一个"空"的Component框架
ng g component empty
复制代码
而后,在路由中添加
const routes: Routes = [
...,
{
path: '**',
component: EmptyComponent
}
]
复制代码
ALL DONE...
如今,就让它们的状态同步吧。
在history mode下很是简单。只需用到官方提供的setUpLocationSync
便可。
export class AppModule implements DoBootstrap {
ngDoBootstrap(appRef: ApplicationRef) {
this.upgrade.bootstrap(document.documentElement, ['phonecatApp']);
// setUpLocationSync 需在UpgradeModule.bootstrap后引用
setUpLocationSync(upgrade);
}
}
复制代码
那在hash mode下呢?那就没这么简单了。
笔者曾经直接使用setUpLocationSync
这个方法致使笔者直接怀疑人生——每次跳转路由都会出现死循环。 为何会出现这种状况呢?setUpLocationSync
这个方法是@angular/router
提供的函数,通常不会出现问题。但此次致使循环的问题,就是出如今这个函数身上。在upgrage.ts中,能够看到
ngUpgrade.$injector.get('$rootScope')
.$on('$locationChangeStart', (_: any, next: string, __: string) => {
const url = resolveUrl(next);
const path = location.normalize(url.pathname);
router.navigateByUrl(path + url.search + url.hash);
});
复制代码
在ng1触发locationChangeStart这个事件后,这个函数直接将URL中的path + url.search + url.hash
传递给ngx的Router,然而hash mode中应该须要将hash做为路径传递。所以,要在hash mode中同步状态,须要将router.navigateByUrl(path + url.search + url.hash);
改成this.router.navigateByUrl(url.hash + url.search)
。
在本文的例子中在原有的setUpLocationSync
的基础上实现了路由器的同步: location-sync.service.ts
在参考文章中升级 AngularJS 至 Angular提到了“相邻路由出口”。
在实际运用中,经过它能够作一些如懒加载的ng1的模块等实现。须要注意的是,若是在组件(Component)中放入ng1的入口,那么调用UpgradeModule.bootstrap须要在该组件视图加载完毕后,如ngAfterViewInit
钩子等等。
在此,你能够获取到本文修改后的angular-phonecat项目。 [github.com/yskun/angul…]
本做品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。