管理系统 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栏切换的更多相关文章

  1. jQuery带有定时器的tab栏切换

    现在网上很多类似选项卡的切换,我们成为tab栏切换,比如下图: 新浪的tab栏切换 淘宝的tab栏切换 其中,新浪的tab栏鼠标放上去,可以快速的来回切换,但是如果采取ajax异步传输,不停去加载服务 ...

  2. dataTable tab栏切换时错位解决办法

    做后台管理类网站肯定要写列表,首选dataTable,功能强大 最近在做一个tab栏切换时发现了一个很诡异的事情:表头错位了! 主要时因为当table被隐藏后,table的header宽度会计算错乱, ...

  3. tab栏切换

    最简单的tab栏切换 html部分 <ul class="tab"> <li class="item">待支付(1)</li> ...

  4. tab栏切换制作

    tab栏切换制作 先上图 要求1:默认状态,第一个选项卡被选中,展示第一个选项卡的内容 策略:第一个选项卡默认有被选中的样式,第一个选项卡对应的display: block,其他的dispaly设为n ...

  5. ES6面向对象实现tab栏切换效果

    面向对象实现tab栏切换效果

  6. JS实现 Tab栏切换案例

    要求:当鼠标点击上面相应的选项卡(tab),下面页面的内容也随之而改变. 结构分析: 全部的内容都放到一个大的盒子里面,盒子里面又可以分为上面和下面两个盒子. 上面的盒子放了 5个li,装着5个小的选 ...

  7. angular实现的tab栏切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. tab栏切换的特殊效果

    在实际的开发过程中,我们可能会遇到这种需求,如下图 左边是三个tab栏,右边是显示内容的div,当鼠标滑到坐标的tab上时,给它一个高亮显示,让它对应的内容在右边的div中显示出来,当鼠标移出的时候把 ...

  9. JavaScript实现Tab栏切换

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 京东网页上,可以看到下面这种tab栏的切换: 我们把模型抽象出来,实现一 ...

随机推荐

  1. 201521123027 <java程序设计>第八周学习总结

    1.本周学习总结 1.1思维导图 2.书面作业 Q1.List中指定元素的删除(题目4-1) 1.1 实验总结 总结:判断List中是否存在指定元素,需要用到equals方法,若存在就用remove进 ...

  2. 201521123007《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...

  3. 201521123005《java程序设计》第三周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.使用思维导图将这些碎片化的概念.知识组织起来.使用工具画出本周学习到的知识点. 参考资料: 百度脑图 XMind 2. 书面作业 ·Q ...

  4. 学号:201521123116 《java程序设计》第一周学习总结

    #1. 本章学习总结了解了班级的纪律和期末成绩组成.本周重点学习了java语言的特点具有简单性和结构中立.明白了jdk是java开发人员使用的一种工具,以及编写一个java程序的所需步骤,懂得了jdk ...

  5. 将缓冲区的数字字符串转化成BCD码数据_INT PubNumericToBCDStr(_UCHR *pcNStr, _INT iNLen, _UCHR *pcBCDStr)

    INT PubNumericToBCDStr(_CHR *pcNStr, _INT iNLen, _CHR *pcBCDStr) { _UCHR *pN = pcNStr; _UCHR *pB = p ...

  6. Android 之xml解析

    HTTP网络传输中的数据组织方式有三种方式:1.HTML方式2.XML方式 3.JSON方式 XML称为可扩展标记语言,它与HTML一样,都是SGML(标准通用标记语言) XML是Internet环境 ...

  7. 解决在Ubuntu终端下使用cURL获取GBK格式的页面出现乱码问题

    问题描述 在Ubuntu下使用终端使用cURL去拿一个GBK的页面,发现返回来的内容里面中文都是乱码 解决方法 通过iconv来处理乱码拿到的内容,进行转码,示例如下: $curl http://ww ...

  8. JAVA实现上传文件到服务器、删除服务器文件

    使用的jar包: <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</art ...

  9. jquery实现点击div外隐藏div

    html <div style="width:100px;height:100px;border:1px solid #ff0" id="div"> ...

  10. snmp4j 之 ArgumentParser

    ArgumentParser ArgumentParser命令行解析器 将数组转换成Java对象 根据预定计划选项和参数,以及相应的命令行选项联合每个对象 ArgumentParser argumen ...