在Angular 2中有没有聪明的方法返回到最后一页?

类似的

this._router.navigate(LASTPAGE);

例如,C页有一个“返回”按钮,

A页-> C页,点击返回A页。 B页-> C页,点击它,回到B页。

路由器有这个历史信息吗?


当前回答

检测到的未更改组件的@Parziphal答案版本:

  import { Location } from '@angular/common';
  import { Router } from '@angular/router';

  constructor(private readonly router: Router, private readonly location: Location) {
    location.onUrlChange(() => this.canGoBack = !!this.router.getCurrentNavigation()?.previousNavigation);
  }

  goBack(): void {
    if (this.canGoBack) {
      this.location.back();
    }
  }

其他回答

也许你想检查之前的历史点是否在你的应用程序中。例如,如果你直接进入你的应用程序并执行location.back()(例如,通过按下工具栏中的<- back按钮),你会回到浏览器的主页面,而不是去应用程序中的其他地方。

这是我检查这个的方法:

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

@Component({
  selector: 'app-foo',
  template: ''
})
export class FooComponent {

  private readonly canGoBack: boolean;

  constructor(
    private readonly route: ActivatedRoute,
    private readonly router: Router,
    private readonly location: Location
  ) {
    // This is where the check is done. Make sure to do this
    // here in the constructor, otherwise `getCurrentNavigation()`
    // will return null. 
    this.canGoBack = !!(this.router.getCurrentNavigation()?.previousNavigation);
  }

  goBack(): void {
    if (this.canGoBack) {
      // We can safely go back to the previous location as
      // we know it's within our app.
      this.location.back();
    } else {
      // There's no previous navigation.
      // Here we decide where to go. For example, let's say the
      // upper level is the index page, so we go up one level.
      this.router.navigate(['..'], {relativeTo: this.route});
    }
  }

}

我们检查加载当前路由的导航是否有前一个兄弟。这必须在导航过程仍处于活动状态时在构造函数中完成。

但也有一些注意事项:

即使之前的位置实际上在我们的应用程序中,但页面被刷新,canGoBack也将为false。 用户可能想通过点击浏览器的返回按钮“返回”到上一页(goBack()发生的地方),但由于应用程序返回历史而不是按一个新的位置,用户将会返回得更远,可能会感到困惑。

在Angular 2的最终版本中。X / 4。x -这里是文档https://angular.io/api/common/Location

/* typescript */

import { Location } from '@angular/common';
// import stuff here

@Component({
// declare component here
})
export class MyComponent {

  // inject location into component constructor
  constructor(private location: Location) { }

  cancel() {
    this.location.back(); // <-- go back to previous location on cancel
  }
}

RC4:

import {Location} from '@angular/common';

你可以在你的路由类上实现routerOnActivate()方法,它会提供之前路由的信息。

routerOnActivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction) : any

然后你可以使用router.navigateByUrl()并传递ComponentInstruction生成的数据。例如:

this._router.navigateByUrl(prevInstruction.urlPath);

此外,您还可以在历史记录为空的情况下使用此服务与回退功能

url-back.service.ts

import { Injectable } from '@angular/core';
import { Location } from '@angular/common';

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

const EMPTY_HISTORY_LENGTH = 2;

/**
 * This service helps to Navigate back to the prev page, and if no prev page,
 * will redirect to the fallback url.
 */
@Injectable()
export class UrlBackService {
  constructor(private router: Router, private location: Location) {}

  /**
   * This method will back you to the previous page,
   * if no previous page exists, will redirect you to the fallback url.
   * @param href - url, if tryNativeFirst is provided, this is fallback url
   * @param tryNativeFirst - try to go back natively using browser history state.
   */
  back(href: string, tryNativeFirst: boolean = false) {
    if (tryNativeFirst) {
      if (history.length === EMPTY_HISTORY_LENGTH) {
        this.router.navigate(UrlBackService.urlToArray(href));
      } else {
        this.location.back();
      }
    } else {
      this.router.navigate(UrlBackService.urlToArray(href));
    }
  }

  /**
   * In case that router.navigate method tries to escape all '/' in the string,
   * was decided to split string to array, and if URL starts or ends with slash - remove them, eg:
   * /my/url will be split to ['', 'my', 'url'], so we need to remove empty spaces use filter function.
   * @param href
   * @private
   */
  private static urlToArray(href: string) {
    return href.split('/').filter((notEmpty) => notEmpty);
  }
}

url-back.service.spec.ts

import { TestBed } from '@angular/core/testing';

import { UrlBackService } from './url-back.service';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';

describe('UrlBackService', () => {
  let service: UrlBackService;
  let router: Router;
  let location: Location;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      providers: [UrlBackService],
    });
    service = TestBed.inject(UrlBackService);
    router = TestBed.inject(Router);
    location = TestBed.inject(Location);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('no meter what history state is, it should be redirected to the /my/url', () => {
    spyOn(router, 'navigate');
    service.back('/my/url');
    expect(router.navigate).toHaveBeenCalledWith(['my', 'url']);
  });

  it('in case history is empty push to /my/url', () => {
    spyOn(router, 'navigate');
    service.back('/my/url', true);
    expect(router.navigate).toHaveBeenCalledWith(['my', 'url']);
  });

  it('in case history is NOT empty push to url1', () => {
    spyOn(location, 'back');
    window.history.pushState(null, '', 'url1');

    service.back('/my/url', true);
    expect(location.back).toHaveBeenCalled();
  });
});