传智播客旗下技术交流社区北京校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

import {ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy} from '@angular/router';

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


interface IRouteConfigData {

reuse: boolean;

}


interface ICachedRoute {

handle: DetachedRouteHandle;

data: IRouteConfigData;

}


@Injectable()

export class AppReuseStrategy implements RouteReuseStrategy {

private static routeCache = new Map<string, ICachedRoute>();

private static waitDelete: string; // 当前页未进行存储时需要删除

private static currentDelete: string; // 当前页存储过时需要删除


/** 进入路由触发,判断是否是同一路由 */

shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {

console.log("shouldReuseRoute",future,curr,future.routeConfig === curr.routeConfig);

return future.routeConfig === curr.routeConfig;

}


/** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断,这里判断是否有data数据判断是否复用 */

shouldDetach(route: ActivatedRouteSnapshot): boolean {

const data = this.getRouteData(route);

if (data) {

console.log("shouldDetach",route,true);

return true;

}

console.log("shouldDetach",route,false);

return false;

}


/** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */

store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {

const url = this.getFullRouteUrl(route);

const data = this.getRouteData(route);

if (AppReuseStrategy.waitDelete && AppReuseStrategy.waitDelete === url) {

// 如果待删除是当前路由,且未存储过则不存储快照

AppReuseStrategy.waitDelete = null;

console.log("store",route,handle,null)

return null;

}else {

// 如果待删除是当前路由,且存储过则不存储快照

if (AppReuseStrategy.currentDelete && AppReuseStrategy.currentDelete === url) {

AppReuseStrategy.currentDelete = null;

console.log("store",route,handle,null)

return null;

}else {

AppReuseStrategy.routeCache.set(url, { handle, data });

this.addRedirectsRecursively(route);

console.log("store",route,handle,"store")

}

}

}


/** 若 path 在缓存中有的都认为允许还原路由 */

shouldAttach(route: ActivatedRouteSnapshot): boolean {

const url = this.getFullRouteUrl(route);

console.log("shouldAttach",AppReuseStrategy.routeCache.has(url))

return AppReuseStrategy.routeCache.has(url);

}


/** 从缓存中获取快照,若无则返回nul */

retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {

const url = this.getFullRouteUrl(route);

// const data = this.getRouteData(route);

console.log("retrieve",route)

return AppReuseStrategy.routeCache.has(url)

? AppReuseStrategy.routeCache.get(url).handle

: null;

}


private addRedirectsRecursively(route: ActivatedRouteSnapshot): void {

const config = route.routeConfig;

if (config) {

if (!config.loadChildren) {

const routeFirstChild = route.firstChild;

const routeFirstChildUrl = routeFirstChild ? this.getRouteUrlPaths(routeFirstChild).join('/') : '';

const childConfigs = config.children;

if (childConfigs) {

const childConfigWithRedirect = childConfigs.find(c => c.path === '' && !!c.redirectTo);

if (childConfigWithRedirect) {

childConfigWithRedirect.redirectTo = routeFirstChildUrl;

}

}

}

route.children.forEach(childRoute => this.addRedirectsRecursively(childRoute));

}

}


private getFullRouteUrl(route: ActivatedRouteSnapshot): string {

let next = route;

// Since navigation is usually relative

// we go down to find out the child to be shown.

while (next.firstChild) {

next = next.firstChild;

}

const segments = [];

// Then build a unique key-path by going to the root.

while (next) {

segments.push(next.url);

next = next.parent;

}

return segments.reverse().join('/');


// return this.getFullRouteUrlPaths(route).filter(Boolean).join('/').replace('/', '_');

}


private getFullRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {

const paths = this.getRouteUrlPaths(route);

return route.parent ? [ ...this.getFullRouteUrlPaths(route.parent), ...paths ] : paths;

}


private getRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {

return route.url.map(urlSegment => urlSegment.path);

}


private getRouteData(route: ActivatedRouteSnapshot): IRouteConfigData {

// return route.routeConfig && route.routeConfig.data as IRouteConfigData;

return route.data as IRouteConfigData;

}


/** 用于删除路由快照*/

public static deleteRouteSnapshot(url: string): void {

if (url[0] === '/') {

url = url.substring(1);

}

url = url.replace('/', '_');

if (AppReuseStrategy.routeCache.has(url)) {

AppReuseStrategy.routeCache.delete(url);

AppReuseStrategy.currentDelete = url;

}else {

AppReuseStrategy.waitDelete = url;

}

}

}

providers: [

{ provide: RouteReuseStrategy, useClass: AppReuseStrategy }

],


//路由列表

menuList: Array<{ title: string, module: string, power: string,isSelect:boolean }>=[];

constructor(

private router: Router,

private activatedRoute: ActivatedRoute,

private titleService: Title) {

//路由事件

this.router.events.pipe(

filter(event => event instanceof NavigationEnd),

map(() => this.activatedRoute),

map(route => {

while (route.firstChild) route = route.firstChild;

return route;

}),

filter(route => route.outlet === 'primary'),

mergeMap(route => route.data)

).subscribe((event) => {

//路由data的标题

let title = event['title'];

if (event.reuse) {

this.menuList.forEach(p => p.isSelect=false);

var menu = { title: title, module: event["module"], power: event["power"], isSelect:true};

this.titleService.setTitle(title);

let exitMenu=this.menuList.find(info=>info.title==title);

if(exitMenu){//如果存在不添加,当前表示选中

this.menuList.forEach(p => p.isSelect=p.title==title);

return ;

}

this.menuList.push(menu);

}

});

}


ngOnInit() {


}


ngOnChanges() {

console.log(this.menuList);

}


closeUrl(module: string, isSelect: boolean, event: Event) {

event.preventDefault();

// 当前关闭的是第几个路由

const index = this.menuList.findIndex(p => p.module === module);

// 如果只有一个不可以关闭

if (this.menuList.length === 1) return;

this.menuList = this.menuList.filter(p => p.module !== module);

// 删除复用

AppReuseStrategy.deleteRouteSnapshot(module);

if (!isSelect) return;

// 显示上一个选中

let menu = this.menuList[index - 1];

if (!menu) {// 如果上一个没有下一个选中

menu = this.menuList[index];

}

this.menuList.forEach(p => p.isSelect = p.module === menu.module);

// 显示当前路由信息

this.router.navigate(['/' + menu.module]);

}


<reusetab

    ="menuList"></reusetab>


    .reuseTab-col {

    display: inline-block;

    height: 100%;

    margin: 0 32px 0 0;

    box-sizing: border-box;

    position: relative;

    transition: color 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);

    cursor: pointer;

    text-decoration: none;

    background-color: white;

    }


    .reuseTab-col:hover {

    color:#40a9ff;

    }

    .reuseTab-col:active {

    color:#40a9ff;

    font-weight:500;

    }

    .reusetab-nav {

    display: block;

    background-color: #fff;

    padding:16px 8px;

    border-bottom:1px solid #d9d9d9;

    outline:none;

    user-select:none;

    }


    <div class="reusetab-nav">

    <div *ngFor="let node of list" class="reuseTab-col" (click)="clickFunc(node)">{{node.title}}</div>

    </div>

    import { Component, OnInit, Input, OnChanges } from '@angular/core';

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


    @Component({

    selector: 'reusetab',

    templateUrl: './reusetab.component.html',

    styleUrls: ['./reusetab.component.css']

    })

    export class ReusetabComponent implements OnInit,OnChanges {


    @Input('list') list;


    constructor(

    // private route:Route,

    private router:Router,

    ) { }


    ngOnInit() {

    }


    ngOnChanges() {

    console.log(this.list);

    }


    clickFunc(node) {

    console.log(node);

    this.router.navigateByUrl(node.module);

    }


    }

    import {filter,map,mergeMap } from 'rxjs/operators';


    filter(event => event instanceof NavigationEnd),

    map(() => this.activatedRoute),

    map(route => {

    while (route.firstChild) route = route.firstChild;

    return route;

    }),

    filter(route => route.outlet === 'primary'),

    mergeMap(route => route.data)


分享至 : QQ空间
收藏

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马
关闭

站长推荐 上一条 /4 下一条