You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 5实现点击链接变色并重置其他链接默认样式

Angular 5指令实现导航链接点击激活并重置其他链接状态

我来帮你搞定这个需求!你想用Angular 5指令实现:点击Materialize导航里的链接时改变文字颜色,且只有当前点击的链接保持高亮,其他所有链接(包括之前点击过的)都恢复默认颜色。

先看看你现有的代码:

导航HTML结构

<ul id="slide-out" class="side-nav fixed">
  <li>
    <a class="link-text-1" appHighlight>
      <span>Parent-alone</span>
    </a>
  </li>
  <li>
    <a class="link-text-2" appHighlight>
      <span>Parent</span>
    </a>
    <ul id="inner" class="inner">
      <li>
        <a class="child-link-1" appHighlight>
          <span>Child-1</span>
        </a>
      </li>
      <li>
        <a class="child-link-2" appHighlight>
          <span>Child-2</span>
        </a>
      </li>
    </ul>
  </li>
</ul>

现有指令代码

import {Directive, ElementRef, HostListener} from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef) { }

  @HostListener('click') clickedLink() {
    this.highlight('red');
  }

  private highlight(color: string) {
    this.el.nativeElement.style.color = color;
  }
}

问题分析

你当前的指令只能单独控制自己绑定的元素,各个指令实例之间没有通信机制。所以当点击新链接时,旧的高亮链接不会自动恢复默认颜色——这就是核心问题。

解决方案:用共享服务实现指令间通信

我们需要一个共享服务来协调所有appHighlight指令的状态:当某个链接被点击时,通过服务通知所有指令,让非当前点击的链接重置样式。

步骤1:创建共享服务

这个服务负责触发激活事件,让所有指令监听并响应状态变化:

import { Injectable, EventEmitter } from '@angular/core';

@Injectable()
export class HighlightService {
  // 定义事件发射器,传递当前激活的元素
  linkActivated = new EventEmitter<HTMLElement>();
}

步骤2:修改HighlightDirective

注入共享服务,实现点击时高亮自身,并通知其他指令重置:

import { Directive, ElementRef, HostListener, OnInit, OnDestroy } from '@angular/core';
import { HighlightService } from './highlight.service';
import { Subscription } from 'rxjs';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective implements OnInit, OnDestroy {
  // 保存元素的默认文字颜色
  private defaultColor: string;
  // 保存订阅对象,防止内存泄漏
  private subscription: Subscription;

  constructor(
    private el: ElementRef,
    private highlightService: HighlightService
  ) {}

  ngOnInit() {
    // 获取元素初始的默认颜色(从计算样式中读取)
    this.defaultColor = getComputedStyle(this.el.nativeElement).color;
    
    // 订阅服务的激活事件:如果当前元素不是激活元素,就重置颜色
    this.subscription = this.highlightService.linkActivated.subscribe(activeEl => {
      if (activeEl !== this.el.nativeElement) {
        this.el.nativeElement.style.color = this.defaultColor;
      }
    });
  }

  @HostListener('click') clickedLink() {
    // 高亮当前链接
    this.highlight('red');
    // 通知服务:当前元素被激活
    this.highlightService.linkActivated.emit(this.el.nativeElement);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.color = color;
  }

  ngOnDestroy() {
    // 组件销毁时取消订阅,避免内存泄漏
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

步骤3:在模块中注册服务和指令

确保在你的Angular模块中提供这个服务,比如AppModule或者相关的功能模块:

import { NgModule } from '@angular/core';
import { HighlightDirective } from './highlight.directive';
import { HighlightService } from './highlight.service';

@NgModule({
  declarations: [HighlightDirective],
  providers: [HighlightService],
  exports: [HighlightDirective]
})
export class HighlightModule {}

进阶优化:用CSS类控制样式(推荐)

直接操作style不够灵活,更推荐用CSS类来管理样式,这样样式和逻辑分离,维护更方便:

  1. 先在CSS中定义默认样式和激活样式:
/* 默认链接颜色 */
.link-text-1, .link-text-2, .child-link-1, .child-link-2 {
  color: #333; /* 替换成你的默认颜色 */
}

/* 激活状态样式 */
.active-link {
  color: red !important;
}
  1. 修改指令,用类来替换直接操作style:
import { Directive, ElementRef, HostListener, OnInit, OnDestroy } from '@angular/core';
import { HighlightService } from './highlight.service';
import { Subscription } from 'rxjs';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective implements OnInit, OnDestroy {
  private subscription: Subscription;

  constructor(
    private el: ElementRef,
    private highlightService: HighlightService
  ) {}

  ngOnInit() {
    this.subscription = this.highlightService.linkActivated.subscribe(activeEl => {
      if (activeEl !== this.el.nativeElement) {
        this.el.nativeElement.classList.remove('active-link');
      }
    });
  }

  @HostListener('click') clickedLink() {
    // 给当前元素添加激活类
    this.el.nativeElement.classList.add('active-link');
    // 通知服务激活事件
    this.highlightService.linkActivated.emit(this.el.nativeElement);
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

这样实现后,每次点击任意带appHighlight指令的链接,都会自动高亮当前链接,同时把其他所有链接的激活状态移除,完美满足你的需求!

内容的提问来源于stack exchange,提问作者Dariusz Mozgowoj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:27:01