Angular 应用如何回退到之前曾经浏览过的页面

简介: Angular 应用如何回退到之前曾经浏览过的页面

我们使用下面的代码,将 Router 注入到应用程序 Component 的构造函数里,然后再调用其 navigate 方法,这种思路只能实现 SPA 应用间的静态路由跳转。

import { Router } from '@angular/router'
@Component({...})
export class UserDetailComponent {
  constructor(private router: Router) {}
  back(): void {
    this.router.navigate('/users')
  }
}


我们可以使用相对路由的思路。

两个点号 .. 代表相对路由:

back(): void {
    this.router.navigate("..");
}


但是,这仅在列表组件注册为具有空路径的子组件时才有效,就像在下面的路由配置中所做的那样。

const routes: Routes = [
  {
    path: 'users',
    component: UsersComponent,
    children: [
      { path: '', component: UserListComponent },
      { path: 'active', component: ActiveUsersComponent },
      { path: ':id', component: UserDetailComponent },
    ],
  },
  { path: '**', redirectTo: 'users' },
]


否则,您必须将点附加到定位的子路由(例如 …/list)。 实际上,这种方法只是在路由层次结构中向上导航一层。


绝对路径和相对路径都不一定会返回到用户之前去过的地方。 它们提供静态导航,并且在开发过程中已经很清楚相应的导航将在何处结束。 因此,即使这是用户在导航到详细信息视图之前所在的位置,也不容易返回到 /users/active. 我们需要找到另一种解决方案来促进这种行为。


浏览器的后退按钮基于浏览器历史记录(browser history)。它有一个 JavaScript API,我们可以使用它在我们的 Angular 应用程序中动态地来回导航。 事实上,Angular 甚至提供 Location 服务作为平台抽象。


该服务有一个 back() 方法,它完全符合我们的要求:它在浏览器的历史记录中向后导航一步。 我们可以将服务注入细节组件或任何中间组件,并在单击按钮时调用它:

import { Location } from '@angular/common'
@Component({...})
export class UserDetailComponent {
  constructor(private location: Location) {}
  back(): void {
    this.location.back()
  }
}


需要注意的是,有一种极端情况:如果应用程序是在打开浏览器或新选项卡后在详细信息路由器上启动的,那么历史记录中将没有可返回的条目。


在这种情况下,location.back() 会将用户从 Angular 应用程序中抛出。 也没有用于直接检查浏览器历史记录的 API,因为这可能会带来安全问题,但我们仍然有办法解决这个问题。


我们将创建一个用于包装后退导航的服务。 在那里,我们还将监听 NavigationEnd 类型的路由器事件,以管理特定于应用程序的导航历史记录。 现在,如果在从堆栈中弹出当前 URL 后历史仍然包含条目,我们可以安全地导航回来。 否则我们将回退到应用程序根目录:

import { Injectable } from '@angular/core'
import { Location } from '@angular/common'
import { Router, NavigationEnd } from '@angular/router'
@Injectable({ providedIn: 'root' })
export class NavigationService {
  private history: string[] = []
  constructor(private router: Router, private location: Location) {
    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.history.push(event.urlAfterRedirects)
      }
    })
  }
  back(): void {
    this.history.pop()
    if (this.history.length > 0) {
      this.location.back()
    } else {
      this.router.navigateByUrl('/')
    }
  }
}

本文完整的源代码已经托管到了 StackBlitz 上,链接如下


2023年1月17日更新


使用 location.replaceState() 将当前 URL 更改为新的给定 URL。 它取代了浏览器历史记录中的顶部项目。


这与 location.go() 非常相似,只有一处不同。 location.go() 将 URL 添加到浏览器历史记录中,而 location.replaceState() 将历史记录中的顶部项替换为新添加的项。


例子:

/projects/core/src/context/services/site-context-routes-handler.ts

1844416ebce148428befbcd718c868f8.png

相关文章
|
4天前
|
JavaScript 前端开发 架构师
Angular进阶:理解RxJS在Angular应用中的高效运用
RxJS(Reactive Extensions for JavaScript)是JavaScript的一个响应式编程库,特别适用于处理异步数据流。
10 0
|
5天前
|
JavaScript 前端开发
Angular.js 应用中数据模式的删除操作实现
Angular.js 应用中数据模式的删除操作实现
16 0
|
5天前
|
存储 JavaScript 前端开发
Angular 应用 node_modules 子文件夹 @types 的作用介绍
Angular 应用 node_modules 子文件夹 @types 的作用介绍
18 1
|
5天前
|
资源调度 JavaScript 编译器
显式指定 npm 作为创建 Angular 应用时的包管理器
显式指定 npm 作为创建 Angular 应用时的包管理器
14 1
|
5天前
|
JavaScript 前端开发
关于 Angular.js 应用里的 $scope.$apply()
关于 Angular.js 应用里的 $scope.$apply()
30 8
|
5天前
|
JavaScript 前端开发
Angular.js 应用里如何发送 HTTP 请求
Angular.js 应用里如何发送 HTTP 请求
20 3
|
5天前
|
JavaScript 前端开发 开发者
【TypeScript技术专栏】TypeScript在Angular开发中的应用
【4月更文挑战第30天】本文探讨了TypeScript在Angular开发中的应用。Angular与TypeScript的结合利用了静态类型检查和ECMAScript特性,简化了大型Web应用的开发。文章涵盖组件、数据绑定、依赖注入、服务、守卫和路由以及模块化等方面,展示了如何在Angular中有效使用TypeScript。此外,还提到了TypeScript的高级应用,如泛型、高级类型和装饰器。掌握这些知识将有助于提升Angular应用的可维护性和可扩展性。
|
5天前
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
|
5天前
|
存储 前端开发 API
浅谈 Angular 应用前端消息显示机制的一个实际需求
浅谈 Angular 应用前端消息显示机制的一个实际需求
13 0
|
5天前
|
设计模式 JavaScript 前端开发
什么是 Angular 应用里的 Custom provider
什么是 Angular 应用里的 Custom provider
33 2