RouterLinkActive不够用,自定义一个RouterLinkActiveStyle

场景,后台自定义底部菜单激活样式,如用户定义的数据为

{
    color: '#000',
    selectedColor: 'red'
}
复制代码

angular提供RouterLinkActive显然不够用了,文档原文说的很清楚,他是css class!

Lets you add a CSS class to an element when the link's route becomes active.
复制代码

下面仿照RouterLinkActive实现一个RouterLinkActiveStyle,下面是RouterLinkActive,通过分析标注需要修改的地方,用todo标注。

import {
  AfterContentInit,
  ChangeDetectorRef,
  ContentChildren,
  Directive,
  ElementRef,
  Input,
  OnChanges,
  OnDestroy,
  QueryList,
  Renderer2,
  SimpleChanges
} from '@angular/core';
import { Subscription } from 'rxjs';

import {
  NavigationEnd,
  RouterEvent,
  Router,
  RouterLink,
  RouterLinkWithHref
} from '@angular/router';

// 修改雷鸣和selector,避免冲突
@Directive({
  selector: '[routerLinkActiveStyle]',
  exportAs: 'routerLinkActiveStyle'
})
export class RouterLinkActiveStyle
  implements OnChanges, OnDestroy, AfterContentInit {
  @ContentChildren(RouterLink, { descendants: true })
  links: QueryList<RouterLink>;
  @ContentChildren(RouterLinkWithHref, { descendants: true })
  linksWithHrefs: QueryList<RouterLinkWithHref>;
  // 保存激活样式数组
  private classes: string[] = [];
  // 保存激活style
  private styles: { [key: string]: any };

  private subscription: Subscription;
  public readonly isActive: boolean = false;

  @Input() routerLinkActiveOptions: { exact: boolean } = { exact: false };

  constructor(
    private router: Router,
    private element: ElementRef,
    private renderer: Renderer2,
    private cdr: ChangeDetectorRef
  ) {
    this.subscription = router.events.subscribe((s: RouterEvent) => {
      if (s instanceof NavigationEnd) {
        this.update();
      }
    });
  }

  ngAfterContentInit(): void {
    this.links.changes.subscribe(_ => this.update());
    this.linksWithHrefs.changes.subscribe(_ => this.update());
    this.update();
  }

  // 设置样式激活数组
  @Input()
  set routerLinkActiveClass(data: string[] | string) {
    const classes = Array.isArray(data) ? data : data.split(' ');
    this.classes = classes.filter(c => !!c);
  }
  // 设置激活style
  @Input()
  set routerLinkActiveStyle(data: { [key: string]: any }) {
    this.styles = data;
  }

  ngOnChanges(changes: SimpleChanges): void {
    this.update();
  }
  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }

  private update(): void {
    if (!this.links || !this.linksWithHrefs || !this.router.navigated) return;
    Promise.resolve().then(() => {
      const hasActiveLinks = this.hasActiveLinks();
      if (this.isActive !== hasActiveLinks) {
        (this as any).isActive = hasActiveLinks;
        if (hasActiveLinks) {
          Object.keys(this.styles).map(res => {
            this.renderer.setStyle(
              this.element.nativeElement,
              res,
              this.styles[res]
            );
          });
        } else {
          Object.keys(this.styles).map(res => {
            this.renderer.removeStyle(this.element.nativeElement, res);
          });
        }
        this.classes.forEach(c => {
          // 生效
          if (hasActiveLinks) {
            this.renderer.addClass(this.element.nativeElement, c);
          } else {
            this.renderer.removeClass(this.element.nativeElement, c);
          }
        });
      }
    });
  }

  private isLinkActive(
    router: Router
  ): (link: RouterLink | RouterLinkWithHref) => boolean {
    return (link: RouterLink | RouterLinkWithHref) =>
      router.isActive(link.urlTree, this.routerLinkActiveOptions.exact);
  }

  private hasActiveLinks(): boolean {
    return (
      this.links.some(this.isLinkActive(this.router)) ||
      this.linksWithHrefs.some(this.isLinkActive(this.router))
    );
  }
}
复制代码

测试使用

<div class="tab-item" [routerLink]="item.pagePath" [routerLinkActiveClass]="activeClass" [routerLinkActiveStyle]="activeStyle" *ngFor="let item of items">
  <p>{{item.text}}</p>
</div>
复制代码
activeStyle = {
    color: this.cfg.selectedColor
}
activeClass = 'active';
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值