RouterLink 指令简介

RouterLink 指令可以让你链接到应用程序的特定部分。若链接是静态的,我们可以按照以下的方式,来使用该指令:

<a routerLink="/user/bob">link to user component</a>

如果你需要使用动态值生成链接地址,你可以传递一个路径片段 (segments) 的数组,然后再传递每个段的参数。例如使用 ['/team',teamId,'user',userName,{details: true}] 数组,意味着我们想要生成一个链接到 /team/11/user/bob;details=true

多个静态段 (segments) 能够被合并为一个,例如 ['/team/11/user',{details: true}]

第一个路径片段可以以 /./../ 开头:

  • 如果以 / 开头,路由将从根路由开始查找

  • 如果以 ./ 开头或没有使用 / ,则路由将从当前激活路由的子路由开始查找

  • 如果以 ../ 开头,路由往上一级查找

你可以使用以下方式设置查询参数和片段 (fragment):

<a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
   link to user component
</a>

RouterLink 指令将基于以上设定的输入参数,生成如下链接:/user/bob#education?debug=true 。此外我们可以通过 queryParamsHandling 属性来声明如何处理查询参数,可用的选项是:

  • merge - 合并已有的 queryParams 到当前的 queryParams

  • preserve - 保存当前的 queryParams

  • default ('') - 仅使用查询参数

具体使用示例如下:

<a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
    link to user component
</a>

RouterLink 指令详解

RouterLink 指令定义

@Directive({selector: ':not(a)[routerLink]'})

RouterLink 指令输入属性

// 设置URL相关的查询参数
@input() queryParams: {[k: string]: any};

// 设置URL上的hash fragment
@input() fragment: string; 

// 设置查询参数处理方式:merge、preserve 、default 
@input() queryParamsHandling: QueryParamsHandling; 

// 设置是否保留fragment
@input() preserveFragment: boolean;

// 设置页面导航时,是否把新的状态添加到历史记录中
@input() skipLocationChange: boolean;

// 设置页面导航的同时,是否替换历史记录中的当前状态
@input() replaceUrl: boolean;
 
// 设置commands参数信息,如:['/user/bob']
@input()
set routerLink(commands: any[]|string) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = [];
    }
}

RouterLink 指令绑定

事件绑定

// 监听RouterLink指令宿主元素的click事件,进行页面切换
@HostListener('click')
onClick(): boolean {
  const extras = {
     skipLocationChange: attrBoolValue(this.skipLocationChange),replaceUrl: attrBoolValue(this.replaceUrl),};
   this.router.navigateByUrl(this.urlTree,extras);
   return true;
}

// 转化设置的属性值为bool值
function attrBoolValue(s: any): boolean {
  return s === '' || !!s;
}

RouterLink 类的构造函数

export class RouterLink { 
    constructor(
      private router: Router,private route: ActivatedRoute,@Attribute('tabindex') tabIndex: string,renderer: Renderer,el: ElementRef) {
        if (tabIndex == null) {
          renderer.setElementAttribute(el.nativeElement,'tabindex','0');
        }
    }
}

@Attribute()

@Attribute('attributeName') 装饰器:用于获取指令宿主元素上 attributeName 属性名对应的属性值。

tabindex

tabindex 属性规定元素的 tab 键控制次序 (当 tab 键用于导航时)。

以下元素支持 tabindex 属性:<a>,<area>,<button>,<input>,<object>,<select> 以及 <textarea>

tabindex 语法:

<element tabindex="number"> <!-- number:规定元素的 tab 键控制次序 (1是第一个)-->

RouterLink 类的属性

// 用于保存commands参数信息
private commands: any[] = [];

// 标识是否保存查询参数,4.0.0版本后用queryParamsHandling代替
private preserve: boolean;

RouterLink 类的方法

// 获取routerLink上配置信息对应的UrlTree
get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands,{
      relativeto: this.route,queryParams: this.queryParams,fragment: this.fragment,preserveQueryParams: attrBoolValue(this.preserve),queryParamsHandling: this.queryParamsHandling,preserveFragment: attrBoolValue(this.preserveFragment),});
}

// angular\packages\router\src\router.ts
// 创建UrlTree
createUrlTree(
    commands: any[],{relativeto,queryParams,fragment,preserveQueryParams,queryParamsHandling,preserveFragment}: 
      NavigationExtras = {}): UrlTree {
    if (isDevMode() && preserveQueryParams && <any>console && <any>console.warn) {
      console.warn('preserveQueryParams is deprecated,use queryParamsHandling instead.');
    }
    const a = relativeto || this.routerState.root;
    const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
    let q: Params|null = null;
    // 根据queryParamsHandling属性值,处理查询参数
    if (queryParamsHandling) {
      switch (queryParamsHandling) {
        case 'merge':
          q = {...this.currentUrlTree.queryParams,...queryParams};
          break;
        case 'preserve':
          q = this.currentUrlTree.queryParams;
          break;
        default:
          q = queryParams || null;
      }
    } else {
      q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null;
    }
    return createUrlTree(a,this.currentUrlTree,commands,q !,f !);
}

RouterLinkWithHref 指令详解

RouterLinkWithHref 指令定义

@Directive({selector: 'a[routerLink]'})

RouterLinkWithHref 指令输入属性

// 设置a标签target的值
@input() target: string;

// 设置URL相关的查询参数
@input() queryParams: {[k: string]: any};

// 设置URL上的hash fragment
@input() fragment: string;

// 设置查询参数处理方式:merge、preserve 、default 
@input() queryParamsHandling: QueryParamsHandling;

// 设置是否保留fragment
@input() preserveFragment: boolean;

// 设置页面导航时,是否把新的状态添加到历史记录中
@input() skipLocationChange: boolean;

// 设置页面导航的同时,是否替换历史记录中的当前状态
@input() replaceUrl: boolean;

// 设置commands信息,如:['/user/bob']
@input()
set routerLink(commands: any[]|string) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = [];
    }
}

RouterLinkWithHref 指令绑定

属性绑定

@HostBinding('attr.target') @input() target: string;
@HostBinding() href: string;

<a> 标签定义超链接,用于从一个页面链接到另外一个页面。<a> 标签中有两个重要的属性:

  • href - 规定链接指向的页面的 URL 地址。如果不使用 href 属性,则不可以使用如下属性:download,media,rel,target 以及 type 属性。

  • target - 规定链接的页面在浏览器窗口中的打开方式,它的参数值主要有:

    • _blank - 在新的浏览器窗口中载入目标文档。

    • _parent - 这个目标使得文档载入父窗口或者包含来超链接引用的框架的框架集。如果这个引用是在窗口或者在顶级框架中,那么它与目标 _self 等效。

    • _self - 这个目标的值对所有没有指定目标的 <a> 标签是默认目标,它使得目标文档载入并显示在相同的框架或者窗口中作为源文档。这个目标是多余且不必要的,除非和文档标题 <base> 标签中的 target 属性一起使用。

    • _top - 这个目标使得文档载入包含这个超链接的窗口,用 _top 目标将会清除所有被包含的框架并将文档载入整个浏览器窗口。

事件绑定

// 监听RouterLink指令宿主元素的click事件,进行页面切换
@HostListener('click',['$event.button','$event.ctrlKey','$event.MetaKey'])
  onClick(button: number,ctrlKey: boolean,MetaKey: boolean): boolean {
    if (button !== 0 || ctrlKey || MetaKey) {
      return true;
    }

    if (typeof this.target === 'string' && this.target != '_self') {
      return true;
    }

    const extras = {
      skipLocationChange: attrBoolValue(this.skipLocationChange),};
    this.router.navigateByUrl(this.urlTree,extras);
    return false;
}

MouseEvent 表示用户与指针设备 (如鼠标) 交互时发生的事件,常见的事件包括:click、dblclick、mouseup 与 mousedown 事件。其中 MouseEvent 对象中包含一个 button 属性,用于表示用户按下的鼠标按键,可能的属性值如下:

  • 0 - 主按键被按下,通常指鼠标左键。

  • 1 - 辅助按键被按下,通常指鼠标滚轮。

  • 2 - 次按键被按下,通常指鼠标右键。

  • 3 - 第四个按钮被按下,通常指浏览器后退按钮。

  • 4 - 第五个按钮被按下,通常指浏览器的前进按钮。

对于配置为左手使用的鼠标,按键操作将正好相反。此种情况下,从右至左读取值。在上面示例代码中,我们还访问了 MouseEvent 对象的 ctrlKeyMetaKey 属性,此外除了这两个属性外 MouseEvent 对象中还包含 altKeyshiftKey 属性。这些属性的相关说明如下:

  • MouseEvent.ctrlKey - 当鼠标事件触发时,如果 control 键被按下,则返回 true。

  • MouseEvent.MetaKey - 当鼠标事件触发时,如果 (Window - ,Mac - ⌘ Command ) 键被按下,则返回 true。

  • MouseEvent.altKey - 当鼠标事件触发的时候,如果 (Window - alt ,Mac - Option ) 键被按下,返回true。

  • MouseEvent.shiftKey - 当鼠标事件触发时,如果 shift 键被按下,则返回 true。

若按下 ctrlKey ,再点击 <a> 标签,则会使用当前的 URL 地址,新建一个新的 tab 页。若按下 MetaKey ,再点击 <a> 标签,则会重新刷新当前页。因此在 onClick() 方法中,才会执行相应的判断。

RouterLinkWithHref 指令生命周期

ngOnChanges()

// 输入属性发生变化时,更新a标签href属性
ngOnChanges(changes: {}): any { 
  this.updateTargetUrlAndHref();
}

ngOnDestroy()

// 指令销毁时,取消路由事件的订阅
ngOnDestroy(): any { 
  this.subscription.unsubscribe(); 
}

RouterLinkWithHref 类的构造函数

export class RouterLinkWithHref implements OnChanges,OnDestroy {
  constructor(
      private router: Router,private locationStrategy: LocationStrategy) {
      // 订阅路由事件,当页面切换成功后更新a标签的href属性
      this.subscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        this.updateTargetUrlAndHref();
      }
    });
  }
}

RouterLinkWithHref 类的属性

// 用于保存commands参数信息
private commands: any[] = [];

// 用于保存取消订阅路由事件订阅的Subscription对象
private subscription: Subscription;

// 标识是否保存查询参数,4.0.0版本后用queryParamsHandling代替
private preserve: boolean;

RouterLinkWithHref 类的方法

// 获取routerLink上配置信息对应的UrlTree
get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands,});
}

// 更新a标签href属性值
private updateTargetUrlAndHref(): void {
    this.href = this.locationStrategy
      .prepareExternalUrl(this.router.serializeUrl(this.urlTree));
}

RouterLinkActive 指令简介

RouterLinkActive 指令允许你在链接的路由变为活动状态时向元素添加 CSS 类。请看一下以下示例:

<a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>

当 URL 地址是 /user/user/bob 时,active-link 类将会被添加到 <a> 标签上。如果 URL 发生变化,则 active-link 类将自动从 <a> 标签上移除。你也可以一次性添加多个类,具体如下:

<a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
<a routerLink="/user/bob" [routerLinkActive]="['class1','class2']">Bob</a>

在应用 routerLinkActive 指令时,你也可以通过 routerLinkActiveOptions 参数,来配置 URL 的匹配方式,具体如下:

<a routerLink="/user/bob" routerLinkActive="active-link" 
  [routerLinkActiveOptions]="{exact: true}">Bob</a>

当配置了 {exact: true} 参数,仅当 URL 地址完全匹配时,active-link 类才会被添加到 <a> 标签上。此外你可以将 RouterLinkActive 实例分配给模板变量,并直接检查指令的 isActive 状态:

<a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
    Bob {{ rla.isActive ? '(already open)' : ''}}
</a>

最后,你也可以将 RouterLinkActive 指令应用于 RouterLink 的父级元素。具体示例如下:

<div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
  <a routerLink="/user/jim">Jim</a>
  <a routerLink="/user/bob">Bob</a>
</div>

在上面示例中,当 URL 的地址为 /user/jim/user/bob 时,active-link 类会被添加到对应的 <div> 元素上。

RouterLinkActive 指令详解

RouterLinkActive 指令定义

@Directive({
  selector: '[routerLinkActive]',exportAs: 'routerLinkActive',})

RouterLinkActive 指令输入属性

// 设置处于激活状态时,宿主元素上应用的class信息
@input()
set routerLinkActive(data: string[]|string) {
  const classes = Array.isArray(data) ? data : data.split(' ');
  this.classes = classes.filter(c => !!c);
}

// 设置URL地址的匹配方式
@input() routerLinkActiveOptions: {exact: boolean} = {exact: false};

RouterLinkActive 指令生命周期

ngAfterContentinit()

// 订阅RouterLink或RouterLinkWithHref集合的changes对象,从而自动更新宿主元素的class信息
ngAfterContentinit(): void {
    this.links.changes.subscribe(_ => this.update());
    this.linksWithHrefs.changes.subscribe(_ => this.update());
    this.update();
}

ngOnChanges()

// 输入属性变化时,更新宿主元素的class信息
ngOnChanges(changes: SimpleChanges): void { this.update(); }

ngOnDestroy()

// 指令销毁时,取消路由事件的订阅
ngOnDestroy(): void { this.subscription.unsubscribe(); }

RouterLinkActive 类的构造函数

export class RouterLinkActive implements OnChanges,OnDestroy,AfterContentinit {
      constructor(
        private router: Router,private element: ElementRef,private renderer: Renderer,private cdr: ChangeDetectorRef) {
         // 订阅路由事件,当页面切换成功后更新宿主元素上的class信息
          this.subscription = router.events.subscribe(s => {
            if (s instanceof NavigationEnd) {
              this.update();
            }
    });
  }
}

RouterLinkActive 类的属性

// 获取RouterLink集合
@ContentChildren(RouterLink,{descendants: true}) links: QueryList<RouterLink>;

// 获取RouterLinkWithHref集合
@ContentChildren(RouterLinkWithHref,{descendants: true})
  linksWithHrefs: QueryList<RouterLinkWithHref>;
  
// 激活状态的样式列表
private classes: string[] = [];

// 用于保存取消订阅路由事件订阅的Subscription对象
private subscription: Subscription;

// 标识是否处于激活状态
private active: boolean = false;

RouterLinkActive 类的方法

// 获取激活状态
get isActive(): boolean { return this.active; }

// 更新宿主元素的class信息
private update(): void {
    if (!this.links || !this.linksWithHrefs || !this.router.navigated) return;
    const hasActiveLinks = this.hasActiveLinks();

    // react only when status has changed to prevent unnecessary dom updates
    if (this.active !== hasActiveLinks) {
      this.classes.forEach(
          c => this.renderer.setElementClass(this.element.nativeElement,c,hasActiveLinks));
      Promise.resolve(hasActiveLinks).then(active => this.active = active);
    }
}

// 判断是否是激活的链接
private isLinkActive(router: Router): (link: (RouterLink|RouterLinkWithHref)) => boolean {
  return (link: RouterLink | RouterLinkWithHref) =>
           router.isActive(link.urlTree,this.routerLinkActiveOptions.exact);
}

// 判断RouterLink或RouterLinkWithHref集合中是否含有激活的链接
private hasActiveLinks(): boolean {
  return this.links.some(this.isLinkActive(this.router)) ||
      this.linksWithHrefs.some(this.isLinkActive(this.router));
}

Angular 4.x Router Link Directives的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. 利用Node实现HTML5离线存储的方法

    这篇文章主要介绍了利用Node实现HTML5离线存储的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. AmazeUI 折叠面板的实现代码

    这篇文章主要介绍了AmazeUI 折叠面板的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码

    这篇文章主要介绍了HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  7. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  9. html5唤起app的方法

    这篇文章主要介绍了html5唤起app的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. HTML5拍照和摄像机功能实战详解

    这篇文章主要介绍了HTML5拍照和摄像机功能实战详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部