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


Posted in Javascript onOctober 21, 2017

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

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

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

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

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

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

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

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

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

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

因为我知道自己对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>

 整体效果如下:

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在网页中控制wmplayer播放器
Jul 01 Javascript
js 判断checkbox是否选中的实现代码
Nov 23 Javascript
网页右键ie不支持event.preventDefault和event.returnValue (需要加window)
Feb 22 Javascript
js实现页面跳转重定向的几种方式
May 29 Javascript
js实现温度计时间样式代码分享
Aug 21 Javascript
jQuery获取checkbox选中的值
Jan 28 Javascript
一个有意思的鼠标点击文字特效jquery代码
Sep 23 jQuery
vue-cli开发环境实现跨域请求的方法
Apr 07 Javascript
vue通过style或者class改变样式的实例代码
Oct 30 Javascript
Node.js+ELK日志规范的实现
May 23 Javascript
vue-cli 3 全局过滤器的实例代码详解
Jun 03 Javascript
微信小程序学习总结(三)条件、模板、文件引用实例分析
Jun 04 Javascript
js Dom实现换肤效果
Oct 21 #Javascript
基于twbsPagination.js分页插件使用心得(分享)
Oct 21 #Javascript
深入浅析ES6 Class 中的 super 关键字
Oct 20 #Javascript
vue做网页开场视频的实例代码
Oct 20 #Javascript
使用JS中的Replace()方法遇到的问题小结
Oct 20 #Javascript
使用ionic(选项卡栏tab) icon(图标) ionic上拉菜单(ActionSheet) 实现通讯录界面切换实例代码
Oct 20 #Javascript
2种简单的js倒计时方式
Oct 20 #Javascript
You might like
PHP htmlspecialchars_decode()函数用法讲解
2019/03/01 PHP
php利用array_search与array_column实现二维数组查找
2019/07/08 PHP
File, FileReader 和 Ajax 文件上传实例分析(php)
2011/04/27 Javascript
浅析Js中的单引号与双引号问题
2013/11/06 Javascript
js操作table示例(个人心得)
2013/11/29 Javascript
jQuery的ready方法详解
2014/11/27 Javascript
javascript实现英文首字母大写
2015/04/23 Javascript
jQuery采用连缀写法实现的折叠菜单效果
2015/09/18 Javascript
微信小程序 地图(map)实例详解
2016/11/16 Javascript
jQuery实现可移动选项的左右下拉列表示例
2016/12/26 Javascript
SVG描边动画
2017/02/23 Javascript
vue.js实现含搜索的多种复选框(附源码)
2017/03/23 Javascript
详解NodeJS框架express的路径映射(路由)功能及控制
2017/03/24 NodeJs
利用forever和pm2部署node.js项目过程
2017/05/10 Javascript
vue文件树组件使用详解
2018/03/29 Javascript
JavaScript中创建原子的方法总结
2018/08/26 Javascript
弱类型语言javascript开发中的一些坑实例小结【变量、函数、数组、对象、作用域等】
2019/08/07 Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
2020/02/19 Javascript
原生JavaScript实现五子棋游戏
2020/11/09 Javascript
javascript实现倒计时提示框
2021/03/02 Javascript
python中安装模块包版本冲突问题的解决
2017/05/02 Python
Python多继承顺序实例分析
2018/05/26 Python
详解python单元测试框架unittest
2018/07/02 Python
10招!看骨灰级Pythoner玩转Python的方法
2019/04/15 Python
超全Python图像处理讲解(多模块实现)
2020/04/13 Python
大数据分析用java还是Python
2020/07/06 Python
python利用 keyboard 库记录键盘事件
2020/10/16 Python
使用django自带的user做外键的方法
2020/11/30 Python
世界最大域名注册商:GoDaddy
2016/07/24 全球购物
师范生实习的个人自我鉴定
2013/10/20 职场文书
2014学年自我鉴定
2014/02/23 职场文书
《蓝色的树叶》教学反思
2014/02/24 职场文书
《庐山的云雾》教学反思
2014/04/22 职场文书
2015年餐厅服务员工作总结
2015/04/23 职场文书
python3中apply函数和lambda函数的使用详解
2022/02/28 Python
golang生成vcf通讯录格式文件详情
2022/03/25 Golang