内容简介:Auxiliary Routes can be helpful for both technical and UX reasons: learn why and how to use them with AngularAuxiliary Routes are independent, secondary routes that can be added to a page along with a primary route. As an example, we can have a side-menu t
Lazy-Loading Auxiliary Routes with Angular — Why and How
Auxiliary Routes can be helpful for both technical and UX reasons: learn why and how to use them with Angular
May 7 ·7min read
Auxiliary Routes are independent, secondary routes that can be added to a page along with a primary route. As an example, we can have a side-menu that lives within the primary route with its own router-outlet
: that’s an auxiliary route.
Why are Auxiliary Routes useful?
Why would you want to add auxiliary routes to your application? Well — I would argue there are two good reasons for doing it: auxiliary routes are helpful for both technical and User Experience reasons.
- In terms of UX, we use them for providing our users the ability to access or toggle portions of the page via the URL. That means you can link your application’s users to deep parts of your application with a simple URL, without them having to click anywhere
- In technical terms, we can also reduce the initial loading time by lazy loading the routes in the same way as we would do with normal full-page routes
Auxiliary Routes can provide two non-trivial improvements to your application — and here’s even further good news: the Angular Router makes working with them a breeze. Let’s learn how! :rocket:
How do we create an Auxiliary Route?
Creating an auxiliary route works in the same way as creating normal routes, with one difference: to create an auxiliary route, we need to assign a name to the router-outlet
element that will host its contents.
That means:
- a router-outlet without a name will render the primary route matched by the URL
- a router-outlet with a name assigned will match and host auxiliary routes
Authentication Popup as an Auxiliary Route
One of the most classic uses of auxiliary routes is creating popups that are also accessible via URL.
For example, I would argue that redirecting users directly to a login popup rather than prompting them to click a button makes for a much better UX. But at the same time, if the login was not requested — why load it ?
While there may be good reasons for doing it beforehand, which we will explore later on, in some cases you simply want to download only the strictly required amount of code your users need to be able to use your app.
Creating a new Library
I assume you have already created an Angular project with the CLI.
I am a huge fan of Angular libraries — and as such, I always recommend to create a separate library (be it within a monorepo or not) if you have a fair amount of code that you can share and reuse between multiple applications.
So — the first thing we do is to create a new library auth
using the CLI:
ng generate library auth
The full source code of the application can be found on GitHub .
A good alternative to that would be Bit.dev . Bit is a cloud component hub. It’s where you publish, document, and organize your components/modules. It’s a pretty quick and easy way to share your code and make it available for reuse, in any repository.
Creating the Sign In and Sign up Modules
Next, we will be creating two modules: sign-in
and sign-up
.
The main module AuthModule
created with the library will simply be used as a routing wapper to these two sub-modules. Of course, they will be lazy-loaded.
Assume we have generated the two modules with the CLI: what we need to do is to provide the routing needed to load their route component:
// sign in module
@NgModule({
declarations: [SignInComponent],
imports: [
CommonModule,
SignInRoutingModule
]
})
export class SignInModule { }// sign in routing module
@NgModule({
imports: [
RouterModule.forChild([{
path: '',
component: SignInComponent
}])
],
exports: [RouterModule]
})
export class SignInRoutingModule {}
The process for SignUpModule
is the same, so we’ll skip it.
Below, we define the two routes and we lazy load them using loadChildren
:
const routes: Route[] = [
{
component: AuthComponent,
path: '',
children: [
{
path: 'sign-in',
loadChildren: () => import('./sign-in/sign-in.module').then(m => m.SignInModule)
},
{
path: 'sign-up',
loadChildren: () => import('./sign-up/sign-up.module').then(m => m.SignUpModule)
},
{
path: '**',
redirectTo: 'sign-in'
}
]
}
];@NgModule({
imports: [
RouterModule.forChild(routes)
],
exports: [RouterModule]
})
export class AuthRoutingModule { }
As we have mentioned, AuthModule
and its component AuthComponent
are simply wrappers around our two sub-routes.
This is what AuthComponent looks like:
@Component({
selector: 'auth',
template: `
<router-outlet></router-outlet>
`
})
export class AuthComponent {}
Our Library’s routing is done! Certainly, our components are still empty, but we will get back to them later on.
Wiring app the application with the Auth library
The first thing we need to do is to create a new router-outlet
in the App component’s template:
// Primary Routing outlet
<router-outlet></router-outlet>// Dialog Routing outlet
<router-outlet name="dialog"></router-outlet>
Now that we have created a secondary router outlet, we can define the routes that will be injected into it.
Let’s open the app.routing.module
file and add a new route in which we will instantiate the new routing library:
const authRoute = {
path: 'auth',
outlet: 'dialog',
loadChildren: () => import('@auth').then(m => m.AuthModule)
};
const routes: Routes = [
authRoute,
// other routes
];@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
As you can see above, thanks to the loadChildren
function, we can lazy load the module AuthModule
and the Angular routing will automatically import the bundled scripts for that module alone.
It’s important to notice that we have added the property outlet
to the routing configuration, which refers to the name of the router outlet we defined in the template in the previous step.
Navigating to Auxiliary Routes
Navigating to auxiliary routes is also possible is the directive routerLink
. Check out below how to navigate to the routes we have just built:
<button [routerLink]="[{ outlets: { dialog: ['auth', 'sign-in'] } }]" > Sign In </button><button [routerLink]="[{ outlets: { dialog: ['auth', 'sign-up'] } }]" > Sign Up </button>
Creating the Sign In and Sign Up Components
It’s now time to create the components for signing in and up into your application.
We will use Angular Material’s Dialog module to display the data as a dialog:
@Component({
selector: 'sign-in',
template: `
<ng-template #dialog>
<div mat-dialog-title>
Sign In
</div>
<div mat-dialog-content>
<div>
<mat-form-field appearance="outline">
<input type="email" placeholder="Email" matInput />
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline">
<input type="password" placeholder="Password" matInput />
</mat-form-field>
</div>
</div>
<div mat-dialog-actions>
<button mat-flat-button color="primary">
Sign In
</button>
</div>
</ng-template>
`,
styleUrls: ['./sign-in.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SignInComponent implements AfterViewInit {
@ViewChild('dialog') template: TemplateRef<any>;
constructor(
private dialog: MatDialog
) { }
ngAfterViewInit() {
this.dialog.open(this.template, { width: '350px' });
}
}
The dialog is closed, but the URL is still the same!
This is a common problem: if the dialog gets closed, the context of being in a certain route should also reset — but those are not actually connected in any way.
That means, we need to handle this situation manually: wee subscribe to the event when the dialog is closed, and then we navigate to the previous route
ngAfterViewInit() {
const ref = this.dialog.open(this.template, { width: '350px'});
ref.afterClosed().subscribe(() => {
this.router.navigate(['']);
});
}
It gets a little bit more complex when you do not know in which route you currently are: in that case, you can strip the auxiliary route from the current primary route and navigate there. The below code should work in most situations:
const urlWithoutAuxiliaryRoute = this.router
.createUrlTree(['.'], { relativeTo: this.route })
.root.children[PRIMARY_OUTLET].toString();
this.router.navigate([urlWithoutAuxiliaryRoute]);
Let’s see it in action!
Here is a preview of what we’ve achieved: try to pay particular attention to the Network tab and see that the bundles are downloaded as I click on the button!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Scratch少儿趣味编程
[ 日] 阿部和广 / 陶 旭 / 人民邮电出版社 / 2014-11 / 59.00元
Scratch 是麻省理工学院设计开发的一款编程工具,是适合少儿学习编程和交流的工具和平台,有中文版且完全免费。本书结合孩子们学习的语文、数学、科学、社会、音乐、体育等科目,手把手地教大家如何用Scratch 设计程序(如设计一个自动写作文的程序),配合各式卡通形象,通俗易懂,寓教于乐。麻省理工学院教授米切尔•瑞斯尼克作序推荐。 本书图文并茂,生动风趣,适合中小学生等初学者自学或在家长的帮助......一起来看看 《Scratch少儿趣味编程》 这本书的介绍吧!