都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中实现比较简单:markdown
angular. module('phonecatApp'). config(['$routeProvider', function config($routeProvider) { $routeProvider. ..., // 此处省略其余路由 otherwise({ template: '' }); } ]); 复制代码
在ngx中,你须要添加一个"空"的Componentapp
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 国际许可协议进行许可。