不可思议的恶 發表於 2019-11-12 20:30:00

angular配置懒加载路由的思路

<p><strong>前言</strong></p>
<p>&nbsp;&nbsp;&nbsp; 本人记性不好,对于别人很容易记住的事情,我愣是记不住,所以还是靠烂笔头来帮我长长记性。</p>
<p> 参考文章:https://blog.csdn.net/xif3681/article/details/84584317</p>
<p><strong>正文</strong></p>
<p>NgModule作为Angular模块的核心,下面首先就来讲一讲。</p>
<p>1.@NgModule的作用:</p>
<ul>
<li>NgModule 最根本的意义是帮助开发者组织业务代码,开发者可以利用 NgModule 把关系比较紧密的组件组织到一起,这是首要的。</li>
<li>NgModule 用来控制组件、指令、管道等是否可以使用,处于同一个 NgModule 里面的组件默认互相可见,而对于外部的组件来说,只能看到 NgModule 导出( exports )的内容,也就是说,如果你定义的 NgModule 不 exports 任何内容,那么外部使用者即使 import 了你这个模块,也没法使用里面定义的任何内容。</li>
<li>NgModule 是打包时候用到的最小单位,打包的时候会检查所有 @NgModule 和路由配置,Angular底层是使用webpack打包。因为Angular已经帮我们配置好了webpack,所以开发者轻松很多,否则就需要自己配置环境。</li>
<li>NgModule 是 Router 进行异步加载的最小单位,Router 能加载的最小单位是模块,而不是组件。当然,模块里面只放一个组件是允许的,很多组件库都是这样做的。</li>
</ul>
<p>2.@NgModule结构说明:</p>
<div class="cnblogs_code">
<pre>@NgModule({ <br>  declarations: [], <span style="color: rgba(51, 153, 102, 1)">//属于当前模块的组件、指令及管道</span><br>  imports: [], <span style="color: rgba(51, 153, 102, 1)">//当前模板所依赖的项,即外部模块(包括httpModule、路由等)</span><br>  export:[],<span style="color: rgba(51, 153, 102, 1)">//声明出应用给其他的module使用</span><br>  providers: [], <span style="color: rgba(51, 153, 102, 1)">//注入服务到当前模块</span><br>  bootstrap: []<span style="color: rgba(51, 153, 102, 1)">//默认启动哪个组件(只有根模块才能设置bootstrap属性)</span><br>}) </pre>
</div>
<p>3.懒加载说明</p>
<p>(1)<code>RouterModule</code>对象提供了两个静态的方法:<code>forRoot()</code>和<code>forChild()</code>来配置路由信息。</p>
<ul>
<li><code>forRoot()<span style="color: rgba(51, 153, 102, 1)">//在主模块中定义主要的路由信息</span></code></li>
<li><code>forChild()</code><code><span style="color: rgba(51, 153, 102, 1)">//</span></code><span style="color: rgba(51, 153, 102, 1)">应用在特性模块(子模块)中</span></li>
</ul>
<p>(2)懒加载:loadChildren</p>
<p>此处并没有将对应的模块加入到AppModule中,而是通过<code>loadChildren</code>属性,告诉Angular路由依据<code>loadChildren</code>属性配置的路径去加载对应的模块。这就是模块懒加载功能的具体应用,当用户访问 /xxx/** 路径的时候,才会加载对应的模块,这减少了应用启动时加载资源的大小。&nbsp;loadChildren的属性值由三部分组成:</p>
<ul>
<li>需要导入Module的相对路径</li>
<li>#分隔符</li>
<li>导出模块类的名称</li>
</ul>
<p>(3)预加载</p>
<p>在使用懒加载的情况下,路由第一次加载某个模块时,有时反应有延迟。这时就可以用预加载策略来解决这个问题。</p>
<p>Angular提供了两种加载策略,</p>
<ul>
<li><code>PreloadAllModules</code>-预加载</li>
<li><code>NoPreloading</code>-没有预加载(默认)。</li>
</ul>
<p><code>RouterModule.forRoo()</code>的<code>第二个参数</code>可以添加配置选项,配置选项中就有一个是<code>preloadingStrategy</code>配置,这个配置是一个预加载策略配置。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 0, 1)">//使用默认预加载-预加载全部模块</span>
import { NgModule } from </span>'@angular/core'; <br>import { AppComponent } from './app.component'; <br>import { routes } from './main.routing'; <br>import { RouterModule } from '@angular/router'; <br><span style="background-color: rgba(244, 143, 173, 1)">import { PreloadAllModules } from '@angular/router';</span> <br>@NgModule({ <br>  declarations: , <br>  imports: [ BrowserModule, RouterModule.forRoot(routes, { <span style="background-color: rgba(244, 143, 173, 1)">preloadingStrategy: PreloadAllModules</span> }) ], <br>  providers: [], <br>  bootstrap: }) <br>export class AppModule { }</pre>
</div>
<p>但是,我们更喜欢自己去控制对模块的预加载,这时就需要自定义预加载策略</p>
<p>A.自定义-5秒后加载所有模块</p>
<p>在app组建的同级新建一个custom-preloading-strategy.ts文件</p>
<div class="cnblogs_code">
<pre>import { Route } from '@angular/router'<span style="color: rgba(0, 0, 0, 1)">;
import { PreloadingStrategy } from </span>'@angular/router'<span style="color: rgba(0, 0, 0, 1)">;
import { Observable } from </span>'rxjs/Rx'<span style="color: rgba(0, 0, 0, 1)">;

export class CustomPreloadingStrategy implements PreloadingStrategy {
    preload(route: Route, fn: () </span>=&gt; Observable&lt;<span style="color: rgba(0, 0, 255, 1)">boolean</span>&gt;): Observable&lt;<span style="color: rgba(0, 0, 255, 1)">boolean</span>&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> Observable.of(<span style="color: rgba(0, 0, 255, 1)">true</span>).delay(5000).flatMap((_: <span style="color: rgba(0, 0, 255, 1)">boolean</span>) =&gt;<span style="color: rgba(0, 0, 0, 1)"> fn());
    }
}</span></pre>
</div>
<p>在app.modules.ts的providers中注入</p>
<div class="cnblogs_code">
<pre>import { BrowserModule } from '@angular/platform-browser'<span style="color: rgba(0, 0, 0, 1)">;
import { NgModule } from </span>'@angular/core'<span style="color: rgba(0, 0, 0, 1)">;

import { AppComponent } from </span>'./app.component'<span style="color: rgba(0, 0, 0, 1)">;
import { HomeComponent } from </span>'./home/home.component'<span style="color: rgba(0, 0, 0, 1)">;
import { routes } from </span>'./main.routing'<span style="color: rgba(0, 0, 0, 1)">;
import { RouterModule } from </span>'@angular/router'<span style="color: rgba(0, 0, 0, 1)">;
<span style="background-color: rgba(244, 143, 173, 1)">import { CustomPreloadingStrategy } from </span></span><span style="background-color: rgba(244, 143, 173, 1)">'./preload'</span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(244, 143, 173, 1)">;</span>

@NgModule({
declarations: [
    AppComponent,
    HomeComponent
],
imports: [
    BrowserModule,
    RouterModule.forRoot(routes, { <span style="background-color: rgba(244, 143, 173, 1)">preloadingStrategy:CustomPreloadingStrategy</span> })
],
providers: [<span style="background-color: rgba(244, 143, 173, 1)">CustomPreloadingStrategy</span> ],
bootstrap:
})
export class AppModule { }</span></pre>
</div>
<p>&nbsp;</p>
<p>B.自定义-指定模块预加载</p>
<p>在app组建的同级新建一个selective-preloading-strategy.ts文件(需要在app-routing.module.ts中的<span style="color: rgba(0, 0, 0, 1)">providers注入,然后在路由中定义的data通过附加参数来设置是否预加载</span>)</p>
<div class="cnblogs_code">
<pre>import { Injectable } from '@angular/core'<span style="color: rgba(0, 0, 0, 1)">;
import { PreloadingStrategy, Route } from </span>'@angular/router'<span style="color: rgba(0, 0, 0, 1)">;
import { Observable} from </span>'rxjs/Observable'<span style="color: rgba(0, 0, 0, 1)">;
import </span>'rxjs/add/observable/of'<span style="color: rgba(0, 0, 0, 1)">;
@Injectable()
export class SelectivePreloadingStrategy implements PreloadingStrategy {
preloadedModules: string[] </span>=<span style="color: rgba(0, 0, 0, 1)"> [];

preload(route: Route, load: () </span>=&gt; Observable&lt;any&gt;): Observable&lt;any&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (route.data &amp;&amp; route.data['preload'<span style="color: rgba(0, 0, 0, 1)">]) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> load();
    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> Observable.of(<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}
}</span></pre>
</div>
<p>&nbsp;</p>
<p>app-routing.module.ts(此文件懒加载与预加载相结合)</p>
<div class="cnblogs_code">
<pre>import { NgModule } from '@angular/core'<span style="color: rgba(0, 0, 0, 1)">;
import { RouterModule, Routes } from </span>'@angular/router'<span style="color: rgba(0, 0, 0, 1)">;
import { CanDeactivateGuard } from </span>'./guard/can-deactivate-guard.service'<span style="color: rgba(0, 0, 0, 1)">;
<span style="background-color: rgba(244, 143, 173, 1)">import { SelectivePreloadingStrategy } from </span></span><span style="background-color: rgba(244, 143, 173, 1)">'./selective-preloading-strategy';</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 预加载</span>
import { PageNotFoundComponent } from './not-found.component'<span style="color: rgba(0, 0, 0, 1)">;
const appRoutes: Routes </span>=<span style="color: rgba(0, 0, 0, 1)"> [
{ path: </span>'', redirectTo: 'home', pathMatch: 'full'<span style="color: rgba(0, 0, 0, 1)">},
<span style="background-color: rgba(244, 143, 173, 1)">{ path: </span></span><span style="background-color: rgba(244, 143, 173, 1)">'mian', loadChildren: './main/mian.module#MainModule' }</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 懒加载(在这个层级的router配置文件及module文件都不需要引入该组建)</span>
{ path: 'home', loadChildren: './home/home.module#HomeModule', <span style="background-color: rgba(244, 143, 173, 1)">data: { preload: <span style="color: rgba(0, 0, 255, 1)">true</span> }</span> }, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 懒加载 + 预加载</span>
{ path: '**', component: PageNotFoundComponent } <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注意要放到最后</span>
<span style="color: rgba(0, 0, 0, 1)">];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes,{
      </span><span style="color: rgba(0, 128, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">enableTracing: true,</span> // &lt;-- debugging purposes only</span>
      <span style="background-color: rgba(244, 143, 173, 1)">preloadingStrategy: SelectivePreloadingStrategy</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 预加载</span>
    <span style="color: rgba(0, 0, 0, 1)">})
  ],
  exports: [
    RouterModule
  ],
  providers: [
    CanDeactivateGuard,
    <span style="background-color: rgba(244, 143, 173, 1)">SelectivePreloadingStrategy</span>
  ]
})
export class AppRoutingModule { }</span></pre>
</div>
<p>&nbsp;</p>
<p>4.子路由创建步骤(没有靠指令创建,直接手动)</p>
<p>(1)新建主文件夹</p>
<p>目录main</p>
<ul>
<li>main.component.html</li>
<li>main.component.scss</li>
<li>main.component.ts</li>
<li>main.module.ts</li>
<li>main-routing.module.ts</li>
<li>main.service.ts
<ul>目录A</ul>
<ul>
<ul class="_mce_act_on">A.component.html</ul>
<ul class="_mce_act_on">A.component.scss</ul>
<ul class="_mce_act_on">A.component.ts</ul>
目录B
<ul class="_mce_act_on">B.component.html</ul>
<ul class="_mce_act_on">B.component.scss</ul>
<ul class="_mce_act_on">B.component.ts</ul>
</ul>
</li>
</ul>
<p class="_mce_tagged_br">&nbsp;</p>
<p class="_mce_tagged_br">比如在上面main.component.html有个区域用于放子视图(以下我都先讲思路,再放关键代码,其他不赘述)</p>
<div class="cnblogs_code">
<pre>&lt;div&gt;下面的区域是另一个路由出口&lt;/div&gt;
&lt;router-outlet&gt;&lt;/router-outlet&gt;<span style="color: rgba(0, 128, 0, 1)">&lt;!--此处依照下面的路由配置,默认显示AComponent组件的内容--&gt;</span></pre>
</div>
<p>(1)在main-routing.module.ts里面配置文件夹main下的路由,需要引用各组件的component(需要配置路由的组件)</p>
<div class="cnblogs_code">
<pre>import {NgModule} from '@angular/core'<span style="color: rgba(0, 0, 0, 1)">;
import {RouterModule, Routes} from </span>'@angular/router'<span style="color: rgba(0, 0, 0, 1)">;
import {MainComponent} from </span>'./main.component'<span style="color: rgba(0, 0, 0, 1)">;
import{AComponent} from </span>'./A/A.component'<span style="color: rgba(0, 0, 0, 1)">;
import{BComponent} from </span>'./B/B.component'<span style="color: rgba(0, 0, 0, 1)">;</span><span style="color: rgba(0, 0, 0, 1)">
const mainRoute: Routes </span>=<span style="color: rgba(0, 0, 0, 1)"> [
{
    path: </span>''<span style="color: rgba(0, 0, 0, 1)">,
    component: MainComponent,
    data: {
      title: </span>'面试预约'<span style="color: rgba(0, 0, 0, 1)">,
    },
    children: [
      {
      path: </span>''<span style="color: rgba(0, 0, 0, 1)">,<span style="color: rgba(0, 128, 0, 1)">//path为空表示默认路由</span>
      component: AComponent,
      data: {
          title: </span>'大活动'<span style="color: rgba(0, 0, 0, 1)">,
      }
      },
      {
      path: </span>'activity'<span style="color: rgba(0, 0, 0, 1)">,
      component: BComponent,
      data: {
          title: </span>'中活动'<span style="color: rgba(0, 0, 0, 1)">,
      }
      }</span><span style="color: rgba(0, 0, 0, 1)">
    ]
}
];


@NgModule({
imports: [
    RouterModule.forChild(main<span style="color: rgba(0, 0, 0, 1)">Route</span>)
],
exports: [
    RouterModule
]
})
export class MainRoutingModule{
}</span></pre>
</div>
<p>(2)main.service.ts一般用于放http请求</p>
<div class="cnblogs_code">
<pre>import { AppService } from './../../app.service'<span style="color: rgba(0, 0, 0, 1)">;
import { Observable } from </span>'rxjs/Observable'<span style="color: rgba(0, 0, 0, 1)">;
import { Injectable } from </span>'@angular/core'<span style="color: rgba(0, 0, 0, 1)">;
import { HttpParams } from </span>'@angular/common/http'<span style="color: rgba(0, 0, 0, 1)">;
import { PageData, ActivitysManage } from </span>'./model/activitys-manage'<span style="color: rgba(0, 0, 0, 1)">;
import { BehaviorSubject } from </span>'rxjs'<span style="color: rgba(0, 0, 0, 1)">;
import {PageDataBig, ActivitySmall, PageDataSmall } from </span>'./model/activitys-manage'<span style="color: rgba(0, 0, 0, 1)">;
@Injectable()
export class MainService {

}</span></pre>
</div>
<p>main文件夹下的组件如要调用MainService,需要在组件的ts文件引入MainService</p>
<p>(3)在main.module.ts中引入各组件(包括自身、路由配置文件所用到的所有组件以及路由的module)</p>
<div class="cnblogs_code">
<pre>import { FormsModule } from '@angular/forms'<span style="color: rgba(0, 0, 0, 1)">;
import { CommonModule } from </span>'@angular/common'<span style="color: rgba(0, 0, 0, 1)">;
import { MainComponent } from </span>'./interview-appointment.component'<span style="color: rgba(0, 0, 0, 1)">;
import { AComponent } from </span>'./A/A.component'<span style="color: rgba(0, 0, 0, 1)">;
import { BComponent } from </span>'./B/B.component'<span style="color: rgba(0, 0, 0, 1)">;</span><span style="color: rgba(0, 0, 0, 1)">
import { NgModule } from </span>'@angular/core'<span style="color: rgba(0, 0, 0, 1)">;
import { CoreFrameCommonModule } from </span>'../../common/common.module'<span style="color: rgba(0, 0, 0, 1)">;
import { MainRoutingModule } from </span>'./main-routing.module'<span style="color: rgba(0, 0, 0, 1)">;
import { NgZorroAntdModule } from </span>'../../zorro/ng-zorro-antd.module'<span style="color: rgba(0, 0, 0, 1)">;</span><span style="color: rgba(0, 0, 0, 1)">
import { MainService } from </span>'./interview-appointment.service'<span style="color: rgba(0, 0, 0, 1)">;
@NgModule({
imports: ,
exports: [],
declarations: ,
providers: ,
})
export class MainModule{ }</span></pre>
</div>
<p>后续更新...</p><br><br>
来源:https://www.cnblogs.com/myyouzi/p/11840067.html
頁: [1]
查看完整版本: angular配置懒加载路由的思路