RouterLinkActive不够用,自定义一个RouterLinkActiveStyle

本文介绍如何在Angular中自定义路由激活时的样式,包括颜色等属性,并提供了具体的实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

{
    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';
复制代码
为了创建一个登录过渡页面,并根据服务器推送的六个参数动态决定角色链接的显示,你可以创建一个基础的HTML模板,结合一些JavaScript来处理参数和条件渲染。这里是一个简单的例子: ```html <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>登录过渡</title> <style> /* 基础样式 */ .login-page { display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f2f2f2; transition: all 0.5s ease-in-out; } .hidden-role { opacity: 0; transition: opacity 0.5s ease-in-out; } .role-links { display: flex; flex-wrap: wrap; } .role-link { width: 30%; margin: 1rem; cursor: pointer; } </style> </head> <body> <div id="login-transition" class="login-page"> <div id="role-links-container"> <ul class="role-links"> <li *ngFor="let role of roles; let i = index" [class.hidden]="shouldHideRole(i)" [routerLink]="[role.route]" routerLinkActive="active"> {{ role.name }} </li> </ul> </div> </div> <script> // 假设从服务器获取的六个参数存储在一个叫roles的数组里 const roles = [ { name: '管理员', route: '/admin', hide: true || false }, ... // 其他五个角色同理 ]; window.onload = function() { updateRolesDisplay(); } function shouldHideRole(index) { return roles[index].hide; } function updateRolesDisplay() { const roleLinks = document.querySelectorAll('.role-links li'); roleLinks.forEach((link, i) => { link.classList.toggle('hidden-role', shouldHideRole(i)); }); } </script> </body> </html> ``` 在这个例子中: - 使用了Angular的指令 `[class.hidden]="shouldHideRole(i)"` 来根据服务器推送的`hide`参数隐藏角色链接。 - JavaScript负责初始化时根据`roles`数组调整每个链接的隐藏状态,当`window.onload`触发时会自动调用`updateRolesDisplay()`函数。 - CSS定义了登录过渡页面的基本样式及角色链接的隐藏效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值