AngularJS 2隐藏位置策略返回导航

时间:2016-03-09 15:38:48

标签: typescript angular

我已经实现了一个简单的LocationStrategy,它会禁用其他股票策略使用的浏览器位置栏更改。我想创建几个较小的应用程序,这些应用程序将被插入任意网页,其中不得触摸浏览器位置,但需要某种导航。这与新战略相得益彰。现在唯一缺少的是back() - 导航功能。显然我不能再调用window.back()但我也没有通过读取角度源找到任何内部方法来调用。我想我可以直接调用LocationStrategy.back(),但我仍然需要一些方法让路由器更新当前视图。是否有一些事件我可以触发或其他东西来存档视图更新?

这是我的位置策略的当前实现:

import { Injectable, Inject, Optional, platform } from 'angular2/core';
import { LocationStrategy, PlatformLocation, APP_BASE_HREF, } from 'angular2/router';
import { joinWithSlash, normalizeQueryParams } from 'angular2/src/router/location_strategy';
import { UrlChangeListener } from 'angular2/src/router/location/platform_location';
import { isPresent } from 'angular2/src/facade/lang';

@Injectable()
export class HiddenLocationStrategy extends LocationStrategy {
    private _baseHref: string = '';
    private pathHistory: string[] = [];
    private poppedPathHistory: string[] = [];
    constructor(private _platformLocation: PlatformLocation,
        @Optional() @Inject(APP_BASE_HREF) _baseHref?: string) {
        super();
        if (isPresent(_baseHref)) {
            this._baseHref = _baseHref;
        }
    }

    onPopState(fn: UrlChangeListener): void {
    }

    getBaseHref(): string { return this._baseHref }

    path(): string {
        return this.pathHistory.length > 0 ? this.pathHistory[this.pathHistory.length - 1] : '';
    }

    prepareExternalUrl(internal: string): string {
        var url = joinWithSlash(this._baseHref, internal);
        return url;
    }

    pushState(state: any, title: string, path: string, queryParams: string) {
        this.pathHistory.push(path);
    }

    replaceState(state: any, title: string, path: string, queryParams: string) {
    }

    forward(): void { this.pathHistory.push(this.poppedPathHistory.pop()); }

    back(): void { this.poppedPathHistory.push(this.pathHistory.pop()); }
}

2 个答案:

答案 0 :(得分:0)

我会尝试提供自定义PlatformLocation https://github.com/angular/angular/blob/master/modules/angular2/src/platform/browser/location/platform_location.ts并调用其forward()back()方法。

abstract onPopState(fn: UrlChangeListener): void;
abstract onHashChange(fn: UrlChangeListener): void;

似乎是路由器订阅的事件。

另见https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate

答案 1 :(得分:0)

该解决方案涉及利用history.pushState API,在pushState方法中放置逻辑,以记录递增标识符(以及您想要的任何其他状态)和onPopState方法中的逻辑评估弹出状态是后向导航还是前向导航,最后是通过包装几个PlatformLocation的方法。

import { APP_BASE_HREF, LocationStrategy, PlatformLocation, Location, LocationChangeListener } from '@angular/common';
import { Inject, Injectable, Optional } from '@angular/core';
import { isPresent } from '@angular/common/src/facade/lang';


export interface HistoryState {
    state: any;
    title: string;
    path: string;
}

@Injectable()
export class HiddenLocationStrategy extends LocationStrategy {
    private baseHref: string = '';
    private pathHistory: HistoryState[] = [];
    private poppedPathHistory: HistoryState[] = [];

    constructor(
        private platformLocation: PlatformLocation,
        @Optional() @Inject(APP_BASE_HREF) baseHref?: string
    ) {
        super();

        if (isPresent(baseHref)) {
            this.baseHref = baseHref;
        }
    }

    onPopState(fn: LocationChangeListener): void {
        this.platformLocation.onPopState((ev: PopStateEvent) => {
            let backward = this.pathHistory.find((item) => item.state.uid === ev.state.uid);
            let forward = this.poppedPathHistory.find((item) => item.state.uid === ev.state.uid);

            if (backward) {
                this.navigateBack();
            } else if (forward) {
                this.navigateForward();
            }

            fn(ev);
        });
        //this.platformLocation.onHashChange(fn);
    }

    getBaseHref(): string {
        return this.baseHref;
    }

    path(): string {
        return this.pathHistory.length > 0
            ? this.pathHistory[this.pathHistory.length - 1].path
            : '';
    }

    prepareExternalUrl(internal: string): string {
        return Location.joinWithSlash(this.baseHref, internal);
    }

    pushState(state: any, title: string, path: string, queryParams: string) {
        state = Object.assign({}, state, {
            uid: (new Date()).valueOf()
        });

        this.pathHistory.push({
            state: state,
            title: title,
            path: path
        });

        this.platformLocation.pushState(state, title, this.prepareExternalUrl(''));
    }

    replaceState(state: any, title: string, path: string, queryParams: string) {
        this.platformLocation.replaceState(state, title, path);
    }

    forward(): void {
        this.platformLocation.forward();
    }

    back(): void {
        this.platformLocation.back();
    }

    private navigateForward() {
        this.pathHistory.push(this.poppedPathHistory.pop());
    }

    private navigateBack() {
        this.poppedPathHistory.push(this.pathHistory.pop());
    }
}