当前位置: 移动技术网 > IT编程>脚本编程>AngularJs > angular4实现tab栏切换的方法示例

angular4实现tab栏切换的方法示例

2017年12月12日  | 移动技术网IT编程  | 我要评论

管理系统 tab 切换页,是一种常见的需求,大概如下:

点击左边菜单,右边显示相应的选项卡,然后不同的选项卡面可以同时编辑,切换时信息不掉失!

用php或.net,java的开发技术,大概是切换显示,然后加一个ifram来做到,或者通过ajax加载信息显示相应的层.

但是如果用angular 要如何实现呢?第一个想法,是否可以用同样的ifarm来实现呢?

第二个想到的是路由插座大概是这样的

复制代码 代码如下:

<router-outlet name="main-content" (activate)="activate($event)" (deactivate)='ondeactivate($event)' ></router-outlet>

但都没能实现,于是在想一个简单的tab页面就这么难吗?

或者真的没有什么简单的方法了吗?

很长一段时间,没有去管这个了

因为我知道自己对angular的理解和学习还不够,于是就放下了很长一段时间,直到在知乎看到一篇文章

angular路由复用策略

于是有了一种思路,花了半天的时间终于实现了anguar 4  tab 切换页大概思路实现如下:

一、实现 routereusestrategy 接口自定义一个路由利用策略

simplereusestrategy.ts代码如下:

import { routereusestrategy, defaulturlserializer, activatedroutesnapshot, detachedroutehandle } from '@angular/router';

export class simplereusestrategy implements routereusestrategy {

  public static handlers: { [key: string]: detachedroutehandle } = {}

  /** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断 */
  public shoulddetach(route: activatedroutesnapshot): boolean {
    return true;
  }

  /** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */
  public store(route: activatedroutesnapshot, handle: detachedroutehandle): void {
    simplereusestrategy.handlers[route.routeconfig.path] = handle
  }

  /** 若 path 在缓存中有的都认为允许还原路由 */
  public shouldattach(route: activatedroutesnapshot): boolean {
    return !!route.routeconfig && !!simplereusestrategy.handlers[route.routeconfig.path]
  }

  /** 从缓存中获取快照,若无则返回nul */
  public retrieve(route: activatedroutesnapshot): detachedroutehandle {
    if (!route.routeconfig) {
      return null
    }
    
    return simplereusestrategy.handlers[route.routeconfig.path]
  }

  /** 进入路由触发,判断是否同一路由 */
  public shouldreuseroute(future: activatedroutesnapshot, curr: activatedroutesnapshot): boolean {
    return future.routeconfig === curr.routeconfig
  }
}

二、策略注册到模块当中:

import { browsermodule } from '@angular/platform-browser';
import { ngmodule } from '@angular/core';
import { formsmodule } from '@angular/forms';
import { commonmodule as systemcommonmodule } from '@angular/common';
import { appcomponent } from './app.component';
import { approutingmodule,componentlist } from './app.routing'
import { simplereusestrategy } from './simplereusestrategy';
import { routereusestrategy } from '@angular/router';

@ngmodule({
 declarations: [
  appcomponent,
  componentlist
 ],
 imports: [
  browsermodule,
  approutingmodule,
  formsmodule,
  systemcommonmodule
 ],
 providers: [
  { provide: routereusestrategy, useclass: simplereusestrategy }
 ],
 bootstrap: [appcomponent]
})
export class appmodule { }

上面两步基本上实现了复用策略但要实现第一张效果图,还是要做一些其它工作

三、定义路由添加一些data数据路由代码如下:

import { ngmodule } from '@angular/core';
import { routes, routermodule } from '@angular/router';
import { aboutcomponent } from './home/about.component'
import { homecomponent } from './home/home.component'
import { newscomponent } from './home/news.component'
import { contactcomponent } from './home/contact.component'



export const routes: routes = [
 { path: '', redirectto: 'home', pathmatch: 'full', },
 { path: 'home', component: homecomponent,data: { title: '首页', module: 'home', power: "show" } },
 { path: 'news',component: newscomponent ,data: { title: '新闻管理', module: 'news', power: "show" }},
 { path: 'contact',component: contactcomponent ,data: { title: '联系我们', module: 'contact', power: "show" }},
 { path: 'about', component: aboutcomponent,data: { title: '关于我们', module: 'about', power: "show" } },
];

@ngmodule({
 imports: [routermodule.forroot(routes)],
 exports: [routermodule]
})

export class approutingmodule { }

export const componentlist=[
  homecomponent,
  newscomponent,
  aboutcomponent,
  contactcomponent
]

四、在<router-outlet></router-outlet> component 实现路由事件  events,app.component代码如下:

import { component } from '@angular/core';
import { simplereusestrategy } from './simplereusestrategy';
import { activatedroute, router, navigationend } from '@angular/router';
import { title } from '@angular/platform-browser';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergemap';

@component({
 selector: 'app-root',
 styleurls:['app.css'],
 templateurl: 'app.html',
 providers: [simplereusestrategy]
})

export class appcomponent {
 
 //路由列表
 menulist: array<{ title: string, module: string, power: string,isselect:boolean }>=[];

 constructor(private router: router,
  private activatedroute: activatedroute,
  private titleservice: title) {
 
  //路由事件
  this.router.events.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'];
    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);
   });
 }

 //关闭选项标签
 closeurl(module:string,isselect:boolean){
  //当前关闭的是第几个路由
  let index=this.menulist.findindex(p=>p.module==module);
  //如果只有一个不可以关闭
  if(this.menulist.length==1) return ;

  this.menulist=this.menulist.filter(p=>p.module!=module);
  //删除复用
  delete simplereusestrategy.handlers[module];
  if(!isselect) return;
  //显示上一个选中
  let menu=this.menulist[index-1];
  if(!menu) {//如果上一个没有下一个选中
    menu=this.menulist[index+1];
  }
  // console.log(menu);
  // console.log(this.menulist);
  this.menulist.foreach(p => p.isselect=p.module==menu.module );
  //显示当前路由信息
  this.router.navigate(['/'+menu.module]);
 }
}
import { component } from '@angular/core';
import { simplereusestrategy } from './simplereusestrategy';
import { activatedroute, router, navigationend } from '@angular/router';
import { title } from '@angular/platform-browser';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergemap';

@component({
 selector: 'app-root',
 styleurls:['app.css'],
 templateurl: 'app.html',
 providers: [simplereusestrategy]
})

export class appcomponent {
 
 //路由列表
 menulist: array<{ title: string, module: string, power: string,isselect:boolean }>=[];

 constructor(private router: router,
  private activatedroute: activatedroute,
  private titleservice: title) {
 
  //路由事件
  this.router.events.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'];
    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);
   });
 }

 //关闭选项标签
 closeurl(module:string,isselect:boolean){
  //当前关闭的是第几个路由
  let index=this.menulist.findindex(p=>p.module==module);
  //如果只有一个不可以关闭
  if(this.menulist.length==1) return ;

  this.menulist=this.menulist.filter(p=>p.module!=module);
  //删除复用
  delete simplereusestrategy.handlers[module];
  if(!isselect) return;
  //显示上一个选中
  let menu=this.menulist[index-1];
  if(!menu) {//如果上一个没有下一个选中
    menu=this.menulist[index+1];
  }
  // console.log(menu);
  // console.log(this.menulist);
  this.menulist.foreach(p => p.isselect=p.module==menu.module );
  //显示当前路由信息
  this.router.navigate(['/'+menu.module]);
 }
}

app.html 的代码如下:

<div class="row">
 <div class="col-md-4">
  <ul>
   <li><a routerlinkactive="active" routerlink="/home">首页</a></li>
   <li><a routerlinkactive="active" routerlink="/about">关于我们</a></li>
   <li><a routerlinkactive="active" routerlink="/news">新闻中心</a></li>
   <li><a routerlinkactive="active" routerlink="/contact">联系我们</a></li>
  </ul>
 </div>
 <div class="col-md-8">
  <div class="crumbs clearfix">
   <ul>
     <ng-container *ngfor="let menu of menulist">
       <ng-container *ngif="menu.isselect">
         <li class="isselect">
           <a routerlink="/{{ menu.module }}">{{ menu.title }}</a> 
           <span (click)="closeurl(menu.module,menu.isselect)">x</span> 
         </li>
       </ng-container>
       <ng-container *ngif="!menu.isselect">
         <li>
           <a routerlink="/{{ menu.module }}">{{ menu.title }}</a> 
           <span (click)="closeurl(menu.module,menu.isselect)">x</span> 
         </li>
       </ng-container>
     </ng-container>
   </ul>
  </div>
  <router-outlet></router-outlet>
 </div>
</div>

 整体效果如下:

最终点击菜单显示相应的标签选中,可以切换编辑内容,关闭标签时,重新点击菜单可以重新加载内容。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网