angular 4 实现的tab栏切换
管理系统 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]);
}
}
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>
整体效果如下:

最终点击菜单显示相应的标签选中,可以切换编辑内容,关闭标签时,重新点击菜单可以重新加载内容。
源代码:好吧,我不知道怎样上传源代码:)!
angular 4 实现的tab栏切换的更多相关文章
- jQuery带有定时器的tab栏切换
现在网上很多类似选项卡的切换,我们成为tab栏切换,比如下图: 新浪的tab栏切换 淘宝的tab栏切换 其中,新浪的tab栏鼠标放上去,可以快速的来回切换,但是如果采取ajax异步传输,不停去加载服务 ...
- dataTable tab栏切换时错位解决办法
做后台管理类网站肯定要写列表,首选dataTable,功能强大 最近在做一个tab栏切换时发现了一个很诡异的事情:表头错位了! 主要时因为当table被隐藏后,table的header宽度会计算错乱, ...
- tab栏切换
最简单的tab栏切换 html部分 <ul class="tab"> <li class="item">待支付(1)</li> ...
- tab栏切换制作
tab栏切换制作 先上图 要求1:默认状态,第一个选项卡被选中,展示第一个选项卡的内容 策略:第一个选项卡默认有被选中的样式,第一个选项卡对应的display: block,其他的dispaly设为n ...
- ES6面向对象实现tab栏切换效果
面向对象实现tab栏切换效果
- JS实现 Tab栏切换案例
要求:当鼠标点击上面相应的选项卡(tab),下面页面的内容也随之而改变. 结构分析: 全部的内容都放到一个大的盒子里面,盒子里面又可以分为上面和下面两个盒子. 上面的盒子放了 5个li,装着5个小的选 ...
- angular实现的tab栏切换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- tab栏切换的特殊效果
在实际的开发过程中,我们可能会遇到这种需求,如下图 左边是三个tab栏,右边是显示内容的div,当鼠标滑到坐标的tab上时,给它一个高亮显示,让它对应的内容在右边的div中显示出来,当鼠标移出的时候把 ...
- JavaScript实现Tab栏切换
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 京东网页上,可以看到下面这种tab栏的切换: 我们把模型抽象出来,实现一 ...
随机推荐
- 201521123111《Java程序设计》第8周学习总结
1. 本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 附上ppt: 1.2 选做:收集你认为有用的代码片段 List strList = new ArrayList ...
- 201521123003《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 我们利用Sca ...
- 201521123085 《JAVA程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 1.clone方法 1.1 Object对 ...
- 201521123063 《Java程序设计》 第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前 ...
- MySql导入导出数据方法
导出全库备份到本地的目录 mysqldump -u$USER -p$PASSWD -h127.0.0.1 -P3306 --routines --default-character-set=utf8 ...
- 注解【介绍、基本Annotation、元Anntation、自定义注解、注入基本信息、对象】
什么是注解? 注解:Annotation-. 注解其实就是代码中的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行相对应的处理. 为什么我们需要用到注解? 传统的方式,我们是通过配置文件(x ...
- Java对象大小:size和retained size
最近看到网上很多文章讲如何计算java对象的大小(size),很多观点不敢苟同. 这是其中一篇比较靠前的文章,写的也比较全面: http://blog.csdn.net/iter_zc/article ...
- Https系列之一:https的简单介绍及SSL证书的生成
Https系列会在下面几篇文章中分别作介绍: 一:https的简单介绍及SSL证书的生成二:https的SSL证书在服务器端的部署,基于tomcat,spring boot三:让服务器同时支持http ...
- Highway Networks
一 .Highway Networks 与 Deep Networks 的关系 深层神经网络相比于浅层神经网络具有更好的效果,在很多方面都已经取得了很好的效果,特别是在图像处理方面已经取得了很大的突破 ...
- pdf去水印
问: 我用Adobe acrobat professional 7.0 版想去掉添加的水印,不知道如何删除,请各位大 侠指点! 答:1.(功能表)工具→高级编辑工具→TouchUp对象工具 2.用滑鼠 ...