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 相关文章推荐
cnblogs csdn 代码运行框实现代码
Nov 02 Javascript
编程语言JavaScript简介
Oct 16 Javascript
深入理解JavaScript系列(29):设计模式之装饰者模式详解
Mar 03 Javascript
jQuery页面刷新(局部、全部)问题分析
Jan 09 Javascript
javascript事件绑定学习要点
Mar 09 Javascript
基于jQuery代码实现圆形菜单展开收缩效果
Feb 13 Javascript
jquery dataTable 后台加载数据并分页实例代码
Jun 07 jQuery
js实现本地图片文件拖拽效果
Jul 18 Javascript
Vue2.5 结合 Element UI 之 Table 和 Pagination 组件实现分页功能
Jan 26 Javascript
js中如何完美的解析数据
Mar 18 Javascript
分享vue里swiper的一些坑
Aug 30 Javascript
js实现div色块碰撞
Jan 16 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
图形数字验证代码
2006/10/09 PHP
配置PHP使之能同时支持GIF和JPEG
2006/10/09 PHP
Smarty Foreach 使用说明
2010/03/23 PHP
CI框架中通过hook的方式实现简单的权限控制
2015/01/07 PHP
PHP中把有符号整型转换为无符号整型方法
2015/05/27 PHP
php实现单笔转账到支付宝功能
2018/10/09 PHP
js 小数取整的函数
2010/05/10 Javascript
javascript测试题练习代码
2012/10/10 Javascript
JavaScript中使用Substring删除字符串最后一个字符
2013/11/03 Javascript
jquery中的过滤操作详细解析
2013/12/02 Javascript
jQuery中parents()方法用法实例
2015/01/07 Javascript
JQueryEasyUI框架下的combobox的取值和绑定的方法
2017/01/22 Javascript
BootStrap table删除指定行的注意事项(笔记整理)
2017/02/05 Javascript
Angular简单验证功能示例
2017/12/22 Javascript
iview table render集成switch开关的实例
2018/03/14 Javascript
Vue3.0数据响应式原理详解
2019/10/09 Javascript
微信小程序监听用户登录事件的实现方法
2019/11/11 Javascript
javascript操作元素的常见方法小结
2019/11/13 Javascript
JavaScript中的函数式编程详解
2020/08/22 Javascript
[53:13]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-GAMING
2014/05/22 DOTA
在python的WEB框架Flask中使用多个配置文件的解决方法
2014/04/18 Python
python中日期和时间格式化输出的方法小结
2015/03/19 Python
python编码最佳实践之总结
2016/02/14 Python
python运行时间的几种方法
2016/06/17 Python
python3 与python2 异常处理的区别与联系
2016/06/19 Python
Python控制多进程与多线程并发数总结
2016/10/26 Python
python web自制框架之接受url传递过来的参数实例
2018/12/17 Python
如何给Python代码进行加密
2020/01/10 Python
Python unittest如何生成HTMLTestRunner模块
2020/09/08 Python
python 基于selectors库实现文件上传与下载
2020/12/31 Python
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
2015/08/31 HTML / CSS
经典c++面试题六
2012/01/18 面试题
户籍证明书标准模板
2014/09/10 职场文书
英语四级考试作弊检讨书
2014/09/29 职场文书
2014年助理工程师工作总结
2014/11/14 职场文书
总经理岗位职责范本
2015/04/01 职场文书