スタック+一方向チェーンはAnglar 11訪問者のブラウズ足跡を実現します.
7618 ワード
アプリケーションでは、足跡をブラウズする必要があります.ナビゲーションバーの後退を実現し、ログイン後のジャンプは、404ページで、前のページに戻ります.ブラウズする時(バック動作でない場合)、データをスタックに押し込んで、バックするとスタックトップがイジェクトされます.一方向チェーンでデータを記憶し、ngx-webstorge-serviceでデータをクライアントに記憶する.データの結証は以下の通りです
B:ナビの後退
後退は命令により実現され、a要素のクラス定義に含まれる限り、
//
export interface TrackItem {
//
previous: string;
//
value: string;
}
A:保存import { ChangeDetectionStrategy, Component, OnInit} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styles: [``],
changeDetection: ChangeDetectionStrategy.Default
})
export class AppComponent implements OnInit {
constructor(
private router: Router,
private footMark: FootmarkTrackService) {
this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: any) => {
//console.log('[App]prev url:', event.url);
this.footMark.save(event.url);
});
}
}
Footmark TrackServiceのコードを添付します.B:ナビの後退
後退は命令により実現され、a要素のクラス定義に含まれる限り、
historyBack
、404マッピングのテンプレート例: のページ
命令の定義は以下の通りですimport { Directive, HostListener } from '@angular/core';
import { Params, Router } from '@angular/router';
@Directive({
selector: 'a.historyBack'
})
export class HistoryBackDirective {
private currentURL: string;
constructor(private router: Router, private footMark: FootmarkTrackService) {
this.currentURL = router.url;
}
@HostListener('click', ['$event.target'])
public backHistory($event: Event): void {
let previousURL: string | null = this.footMark.getPrevious();
let data: { path: string, queryParams: Params } = this.footMark.processURL(previousURL || '/home');
this.router.navigate([data.path], { queryParams: data.queryParams });
}
}
C:登録時にソースを取得する:Refererimport { Component, OnInit } from '@angular/core';
import { Params, Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styles: [``]
})
export class LoginComponent implements OnInit {
public member: { names: string, pswd: string, redirect: string } = {
names: '',
pswd: '',
redirect: ''
};
private previousUrl!: string | null;
constructor(private router: Router, private footMark: FootmarkTrackService) {}
ngOnInit(): void {
this.previousUrl = this.footMark.getReferer();
}
//
private storeMember(): void {
//ETC
//
this.processRedirectURL(this.member.redirect || this.previousUrl);
}
private processRedirectURL(argDedirectURL: string | null): void {
//
let redirectURL: string = argDedirectURL || '/home';
let data: { path: string, queryParams: Params } = this.footMark.processURL(redirectURL);
this.router.navigate([data.path], { queryParams: data.queryParams });
}
}
D:Footmark TrackServiceimport { Injectable, Inject } from '@angular/core';
import { Params } from '@angular/router';
import { StorageService, SESSION_STORAGE } from 'ngx-webstorage-service';
@Injectable({
providedIn: 'root'
})
export class FootmarkTrackService {
private ftKey: string = 'ftStack';
//
// : 1) . , ; 2) referer
constructor(@Inject(SESSION_STORAGE) private storage: StorageService) { }
/**
* /
* @param url
*/
public save(url: string): void {
let data: TrackItem[] = [];
let lastEle: TrackItem | undefined = undefined;
if (this.exist()) {
data = this.get();
lastEle = data[data.length - 1];
}
//
let previousURL: string = lastEle?.value ?? '';
if (previousURL === url) { // ;
return;
}
let pr: TrackItem = { previous: previousURL, value: url };
data.push(pr);
this.storage.set(this.ftKey, data);
}
/**
*
* :/member/login(|register|offline); :/404
* @param url
* @returns
*/
private isIgnoreURL(url: string): boolean {
return url.startsWith('/member/login') || url.startsWith('/member/register') || url.startsWith('/member/offline') || url.startsWith('/404');
}
/**
* /
* @returns
*/
private exist(): boolean {
return this.storage.has(this.ftKey);
}
/**
* (2) Referer
* :LoginComponent.ngOnInit ; constructor
* @returns
*/
public getReferer(): string | null {
if (!this.exist()) {
return null;
}
//
let data: TrackItem[] = this.get();
//
let lastEle: TrackItem | undefined = data[data.length - 1];
return lastEle?.previous ?? null;
}
/**
*
* @returns
*/
private get(): TrackItem[] {
return this.storage.get(this.ftKey);
}
/**
* (1)
* : , :1>A->login, 2>login->A A, A(2>) .getPreviousRef
* @returns
*/
public getPrevious(): string | null {
if (!this.exist()) {
return null;
}
let data: TrackItem[] = this.get();
//
let result: string | null = null;
do {
let lastEle: TrackItem | undefined = data.pop();
if (lastEle && typeof (lastEle.previous) !== 'undefined') {
result = lastEle.previous;
if (this.isIgnoreURL(result)) {
result = null;
}
}
} while (result === null);
//
this.storage.set(this.ftKey, data);
return result;
}
/**
* (1)
* getPrevious
* @param refUrl
* @returns
*/
public getPreviousRef(refUrl: string): string | null {
if (!this.exist()) {
return null;
}
let data: TrackItem[] = this.get();
//
let lastShowIndex: number = -1;
for (let i: number = data.length - 1; i >= 0; i--) {
if (data[i].previous === refUrl) {
lastShowIndex = i;
break;
}
}
// ,
if(lastShowIndex > 0){
data = data.slice(0, lastShowIndex);
}
//
let lastEle: TrackItem | undefined = data.pop();
let result: string | null = lastEle?.previous ?? null;
//
if (result !== null && this.isIgnoreURL(result)) {
result = data.pop()?.previous ?? null;
}
//
this.storage.set(this.ftKey, data);
return result;
}
// redirect
public processURL(redirectURL: string): { path: string, queryParams: Params } {
let p: any;
let qs: Params = {};
if (redirectURL.indexOf('?') == -1) {
p = redirectURL;
} else {
p = redirectURL.substring(0, redirectURL.indexOf('?'));
let queryString = redirectURL.substring(redirectURL.indexOf('?') + 1);
if (queryString) {
let segment: string[] = queryString.split('&');
segment.forEach(ele => {
let kv: string[] = ele.split('=');
if (kv.length == 2) {
qs[kv[0]] = kv[1];
}
});
}
}
return { path: p, queryParams: qs };
}
}
//
export interface TrackItem {
//
previous: string;
//
value: string;
}
図: