>  기사  >  웹 프론트엔드  >  Angle4에서 탭바 전환 구현 방법 공유

Angle4에서 탭바 전환 구현 방법 공유

小云云
小云云원래의
2018-01-04 13:03:252190검색

이 글은 주로 Angular4에서 탭바 전환을 구현하는 방법에 대한 예시를 소개하고 있습니다. 에디터가 꽤 좋다고 생각해서 지금 공유하고 참고용으로 올려보겠습니다. 편집자를 따라 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.

관리 시스템 탭 전환은 대략 다음과 같은 일반적인 요구 사항입니다.

왼쪽 메뉴를 클릭하면 해당 탭이 오른쪽에 표시되고 정보 손실 없이 여러 탭을 동시에 편집할 수 있습니다. 전환할 때!

PHP 또는 .net, Java 개발 기술을 사용하고 아마도 디스플레이를 전환한 다음 iram을 추가하거나 ajax를 통해 정보를 로드하여 해당 레이어를 표시합니다.

그러나 각도를 사용하는 경우 어떻게 구현합니까? 첫 번째 아이디어는 동일한 ifarm을 사용하여 구현할 수 있습니까?

두 번째로 떠오르는 것은 라우팅 아웃렛이 이런 모습이라는 것입니다

코드를 복사하세요 코드는 다음과 같습니다.


3ab937d525951088684486f9037b9fe3d643f9f2456fe4db0e530134a61924e2

근데 그걸 이루지 못해서 간단한 탭 페이지가 그렇게 어려운 건 아닌가 고민 중이었습니다. ?

아니면 정말 간단한 방법이 없을까요?

오랜동안 신경쓰지 않았는데

Angular에 대한 이해와 학습이 부족하다는 걸 알기에 Zhihu에 대한 기사를 보기 전까지 오랫동안 내려놓았습니다

Angular 라우팅 리뷰 전략 사용

그래서 아이디어가 떠올랐고, 마침내 anguar 4 탭 전환 페이지를 구현하는 데 반나절이 걸렸습니다. 일반적인 아이디어는 다음과 같습니다.

1 라우팅 활용을 사용자 정의하기 위해 RouteReuseStrategy 인터페이스를 구현합니다. strategy

SimpleReuseStrategy.ts code 다음과 같습니다:


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
  }
}

2. 모듈에 전략을 등록합니다:


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 { }

위의 두 단계는 기본적으로 재사용 전략을 구현하지만 첫 번째 단계를 달성하려면 렌더링을 수행하려면 아직 다른 작업이 필요합니다.

3. 다음과 같이 경로를 정의하고 일부 데이터 데이터 라우팅 코드를 추가합니다.


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
]

4. d643f9f2456fe4db0e530134a61924e2 컴포넌트 이벤트, app.comComponent 코드는 다음과 같습니다.


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 === &#39;primary&#39;)
   .mergeMap(route => route.data)
   .subscribe((event) => {
    //路由data的标题
    let title = event[&#39;title&#39;];
    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([&#39;/&#39;+menu.module]);
 }
}
import { Component } from &#39;@angular/core&#39;;
import { SimpleReuseStrategy } from &#39;./SimpleReuseStrategy&#39;;
import { ActivatedRoute, Router, NavigationEnd } from &#39;@angular/router&#39;;
import { Title } from &#39;@angular/platform-browser&#39;;
import &#39;rxjs/add/operator/filter&#39;;
import &#39;rxjs/add/operator/map&#39;;
import &#39;rxjs/add/operator/mergeMap&#39;;

@Component({
 selector: &#39;app-root&#39;,
 styleUrls:[&#39;app.css&#39;],
 templateUrl: &#39;app.html&#39;,
 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 === &#39;primary&#39;)
   .mergeMap(route => route.data)
   .subscribe((event) => {
    //路由data的标题
    let title = event[&#39;title&#39;];
    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([&#39;/&#39;+menu.module]);
 }
}

app.html 코드는 다음과 같습니다.


<p class="row">
 <p 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>
 </p>
 <p class="col-md-8">
  <p 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>
  </p>
  <router-outlet></router-outlet>
 </p>
</p>

전체적인 효과는 다음과 같습니다.

마지막으로 메뉴를 클릭하면 해당 라벨이 표시됩니다. 선택하면 편집 내용을 전환하고 라벨을 닫을 수 있으며, 메뉴를 다시 클릭하면 콘텐츠를 다시 로드할 수 있습니다.

관련 권장 사항:

탭 바의 전환 효과를 얻는 방법

DOM

php에서 탭 바의 전환 효과를 구현하여 탭으로 구분된 파일을 읽고 쓸 수 있도록 구현

위 내용은 Angle4에서 탭바 전환 구현 방법 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.