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

不使用localStorage和Service,跨Angular组件保留mat-tab选中状态

无需LocalStorage/Service的Angular Mat-Tab状态保留方案

以下提供两种基于Angular路由机制的实现方案,完全不需要依赖全局Service或LocalStorage:


方案1:使用路由导航状态(NavigationExtras)

该方案将tab状态存储在浏览器历史记录的导航状态中,不会暴露在URL里,适合临时保留状态、不需要刷新后仍生效的场景。

Component A 实现代码

import { Component } from '@angular/core';
import { Router, NavigationExtras } from '@angular/router';
import { MatTabChangeEvent } from '@angular/material/tabs';

@Component({
  selector: 'app-component-a',
  template: `
    <mat-tab-group [(selectedIndex)]="selectedTabIndex" (selectedTabChange)="onTabChange($event)">
      <mat-tab label="标签1">内容1</mat-tab>
      <mat-tab label="标签2">内容2</mat-tab>
      <mat-tab label="标签3">内容3</mat-tab>
    </mat-tab-group>
    <button mat-button (click)="goToComponentB()">跳转到组件B</button>
  `
})
export class ComponentA {
  selectedTabIndex = 0;

  constructor(private router: Router) {
    // 从路由导航状态恢复之前选中的tab索引
    const savedIndex = this.router.getCurrentNavigation()?.extras.state?.['tabIndex'];
    if (savedIndex !== undefined) {
      this.selectedTabIndex = savedIndex;
    }
  }

  onTabChange(event: MatTabChangeEvent) {
    this.selectedTabIndex = event.index;
  }

  goToComponentB() {
    const navigationExtras: NavigationExtras = {
      state: { tabIndex: this.selectedTabIndex }
    };
    this.router.navigate(['/component-b'], navigationExtras);
  }
}

Component B 实现代码

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-component-b',
  template: `
    <h2>组件B内容</h2>
    <button mat-button (click)="goBackToComponentA()">返回组件A</button>
  `
})
export class ComponentB {
  constructor(private router: Router) {}

  goBackToComponentA() {
    // 返回时无需额外传参,状态已保存在历史记录中
    this.router.navigate(['/component-a']);
  }
}

方案2:使用路由查询参数

该方案将tab索引作为查询参数附加在URL中,适合需要刷新页面后仍能保留tab状态的场景。

Component A 实现代码

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { MatTabChangeEvent } from '@angular/material/tabs';

@Component({
  selector: 'app-component-a',
  template: `
    <mat-tab-group [(selectedIndex)]="selectedTabIndex" (selectedTabChange)="onTabChange($event)">
      <mat-tab label="标签1">内容1</mat-tab>
      <mat-tab label="标签2">内容2</mat-tab>
      <mat-tab label="标签3">内容3</mat-tab>
    </mat-tab-group>
    <button mat-button (click)="goToComponentB()">跳转到组件B</button>
  `
})
export class ComponentA implements OnInit {
  selectedTabIndex = 0;

  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute
  ) {}

  ngOnInit() {
    // 从URL查询参数读取保存的tab索引
    const tabIndexParam = this.activatedRoute.snapshot.queryParamMap.get('tabIndex');
    if (tabIndexParam) {
      this.selectedTabIndex = parseInt(tabIndexParam, 10);
    }
  }

  onTabChange(event: MatTabChangeEvent) {
    this.selectedTabIndex = event.index;
    // 更新当前路由的查询参数,实时保存tab状态
    this.router.navigate([], {
      relativeTo: this.activatedRoute,
      queryParams: { tabIndex: this.selectedTabIndex },
      queryParamsHandling: 'merge'
    });
  }

  goToComponentB() {
    // 跳转时携带tab索引参数
    this.router.navigate(['/component-b'], {
      queryParams: { tabIndex: this.selectedTabIndex }
    });
  }
}

Component B 实现代码

import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-component-b',
  template: `
    <h2>组件B内容</h2>
    <button mat-button (click)="goBackToComponentA()">返回组件A</button>
  `
})
export class ComponentB {
  private tabIndex = 0;

  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute
  ) {
    // 接收组件A传来的tab索引参数
    const tabIndexParam = this.activatedRoute.snapshot.queryParamMap.get('tabIndex');
    if (tabIndexParam) {
      this.tabIndex = parseInt(tabIndexParam, 10);
    }
  }

  goBackToComponentA() {
    // 返回时携带tab索引参数
    this.router.navigate(['/component-a'], {
      queryParams: { tabIndex: this.tabIndex }
    });
  }
}

方案对比

  • 路由导航状态:状态仅存在于当前浏览器会话的历史记录中,刷新页面后丢失,无URL污染
  • 查询参数:状态可见于URL,刷新页面后仍能恢复,但会增加URL长度

内容的提问来源于stack exchange,提问作者Pranav Parmar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:00:25