angular11源码探索二十三[路由forRoot]

forRoot

rotRoot: 静态方法是配置根路由模块为您的应用程序的方法。调用时RouterModule.forRoot(routes),要求AngularRouter全局实例化该类的实例,Angular创建一个新的基础AppModule来导入所有功能模块一样,它也提供了AppRoutingModule导入所有子路径的功能。该forRoot方法实际上已经在中使用了app-routing.module.ts。在您的应用中,您只想使用forRoot一次该方法。这是因为此方法告诉Angular在后台实例化该类的实例Router,并且您的应用程序中只能有一个路由器,如果您--routing在创建应用程序时使用参数,则无需担心使用该forRoot方法,因为它已经为您设置好了

app-routing.module.ts

imports: [RouterModule.forRoot(routes)],
forRoot(routes: Routes, config?: ExtraOptions)

源码位置

这边我们主要探究第二个参数

ExtraOptions

interface ExtraOptions {
    // 当为true时,将所有内部导航事件记录到控制台。
    // 用于调试导航的事件
  enableTracing?: boolean
  // 当为true时,启用使用URL片段的#  就是哈希路由
  useHash?: boolean
  // type InitialNavigation = 'disabled'|'enabled'|'enabledBlocking'|'enabledNonBlocking';  
  // 默认  enabledNonBlocking 在创建根组件之后开始初始导航。初始导航完成后,引导程序不会被阻止
 // 'enabledBlocking'-初始导航在创建根组件之前开始。引导程序将被阻止,直到完成初始导航为止。该值是服务器端渲染正常工作所必需的。 
    // 'disabled'-不执行初始导航。在创建根组件之前设置位置侦听器。如果由于某种复杂的初始化逻辑,有理由对路由器何时开始其初始导航有更多的控制权,请使用。
    // 'enabled' angular 11不推荐使用
  initialNavigation?: InitialNavigation
  errorHandler?: ErrorHandler
  // 预加载策略  
  preloadingStrategy?: any
   // 定义路由器在收到对当前URL的导航请求时应采取的措施
   //  ignore  默认  这将导致路由器忽略导航
   // reload   使用此选项来配置导航到当前URL时的行为,
    // 思考了很久,'reload'并不会真正的执行加载工作,它只是重新触发了路由上的events事件循环。
    // 这个用意不是很明显, 我发现默认情况下也会触发路由事件,暂时先放放吧
  onSameUrlNavigation?: 'reload' | 'ignore'
   // 配置向后导航时是否需要恢复滚动位置 
   // 'disabled'-(默认)不执行任何操作。滚动位置在导航上保持不变。
  // 'top'-在所有导航上将滚动位置设置为x = 0,y = 0。
 // 'enabled'-在向后导航时恢复上一个滚动位置,如果提供了导航,则将位置设置为锚点,或者将滚动位置设置为[0,0](正向导航)。此选项将在将来成为默认选项。
    //我在angular9学习第5篇讲过
  scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'
  // 是否滚动到该元素  (锚定滚动)
   //'disabled' -不执行任何操作(默认)。
  // 'enabled'-滚动到元素。此选项将在将来成为默认选项。 
  anchorScrolling?: 'disabled' | 'enabled'
    // 配置路由器滚动到某个元素时将使用的滚动偏移量。当给定具有x和y位置值的元组时,路由器每次滚动时都会使用该偏移量。给定功能后,路由器每次恢复滚动位置时都会调用该功能。
  scrollOffset?: [number, number] | (() => [number, number])
  // 定义路由器如何将参数,数据和已解析的数据从父路由合并到子路由
    // 默认情况下(“ emptyOnly”),仅继承无路径或无组件路由的父参数
    // 设置为“ always”始终启用父参数的无条件继承。
  paramsInheritanceStrategy?: 'emptyOnly' | 'always'
    //错误处理...这个稍等
  malformedUriErrorHandler?: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
  // 定义路由器何时更新浏览器URL
  // 默认 deferred  在成功导航后进行更新。如果希望在导航开始时更新URL
  // eager  尽早更新URL,可以通过显示带有失败URL的错误消息来处理导航失败
  urlUpdateStrategy?: 'deferred' | 'eager'
    // 这是本来有个bug,然后修复了,所以设置成了 'corrected'
    // 启用错误修复程序,以更正具有空路径的组件中的相对路径
    // https://github.com/angular/angular/issues/19290
    // 相对导航到被空/无组件路线折断的兄弟姐妹
  relativeLinkResolution?: 'legacy' | 'corrected'
}
文档网址
https://angular.io/api/router/ExtraOptions

onSameUrlNavigation

'reload'并不会真正的执行加载工作,它只是重新触发了路由上的events事件循环。
当我们设置了 reload 的时候
在页面上使用,我们发现当在当前路由的时候,点击当前路由的导航不会触发事件
  this.router.events.pipe(
      filter(v=>v instanceof NavigationEnd)
    ).subscribe(
      res=>console.log(res);
    )
但是当我们点击其他路由都会触发当前路由的事件,我想它的用意就是这个
如果我们本来在当前路由,点击当前路由的时候想触发事件的话
那我们需要做的是: 修改防护路由的策略,使其每次点击都会触发,路由守卫

这个跟路由守卫没有关联,试了只会当前进来的时候出发一次

anchorScrolling

锚点滚动

设置
anchorScrolling:enabled
这个社会了就相当于可以在网址上面设置 #add执行锚点,启动描点定位

下面这种方法好像直接可以执行不需要设置
<h1 id="add">add</h1>
<button (click)="clickMethod('add')">++</button>

export class TwoComponent implements OnInit, AfterViewInit, OnChanges {
 constructor(
              private viewPort:ViewportScroller,
  ) {}
  
   clickMethod(str: string) {
    this.viewPort.scrollToAnchor(str)
  } 
}    
添加平滑效果
html{
  scroll-behavior: smooth;
}

paramsInheritanceStrategy

上案例

paramsInheritanceStrategy : 'always'
启用父参数的无条件继承。

	{
        path: 'a', component: AComponent, children: [
          {path:'user',component:CComponent}
        ]
      },
  A.html中
<a routerLink="user">11111</a><br>
<a [routerLink]="['user']">122222</a>
当前路由在`/a`上, 两种方式都会跳到  `a/user`
如果不想继承可以写绝对定位

relativeLinkResolution

https://angular.io/api/router/ExtraOptions#relativeLinkResolution

const routes = [
  {
    path: '',
    component: ContainerComponent,
    children: [
      { path: 'a', component: AComponent },
      { path: 'b', component: BComponent },
    ]
  }
];
从中ContainerComponent,这将不起作用:

<a [routerLink]="['./a']">Link to A</a>

但是,这将起作用:

<a [routerLink]="['../a']">Link to A</a>

换句话说,您需要使用../而不是./。

v11中的默认值为corrected。

forChild

forChild: 当您使用forChild静态方法时,Router应用程序中已有一个实例,因此请向该实例注册所有这些路由

注意forChild上面方法的使用。由于您已经使用了该forRoot方法,因此只想注册到已实例化的应用路由器的路由

preloadingStrategy

预加载策略

  • NoPreloading-不预加载任何模块,这是默认行为

  • PreloadAllModules-所有模块都尽可能快地预加载

    参考angular9 的学习九

    它的目标就是,如果我们很多模块都是懒加载,但是其中有些需要预先加载,可以这样使用

ViewportScroller

源码angular-master/packages/common/src/viewport_scroller.ts

定义滚动位置管理器

在angular9学习八也写到过

abstract class ViewportScroller {
    // 配置滚动到锚点时使用的顶部偏移量。
  abstract setOffset(offset: [number, number] | (() => [number, number])): void
   // 检索当前滚动位置。 
  abstract getScrollPosition(): [number, number]
// 滚动到指定位置。
  abstract scrollToPosition(position: [number, number]): void
  // 滚动到锚点元素。
  abstract scrollToAnchor(anchor: string): void
  // 禁用浏览器提供的自动滚动恢复
  abstract setHistoryScrollRestoration(scrollRestoration: "auto" | "manual"): void
}

setOffset()

配置滚动到锚点时使用的顶部偏移量。

[x,y]
   clickMethod() {
    this.viewport.setOffset([0,1000])
    this.viewport.scrollToAnchor('ddd')
  }

posted @ 2021-01-20 00:42  猫神甜辣酱  阅读(522)  评论(0编辑  收藏  举报