功能说明:权限控制
1. 先创建一个service,用户获取用户信息
2. 然后自定义一个结构指令directive(改写ngIf指令):
传入需要的权限,根据调用service获取的用户信息,判断是否有权限,如果有权限,则显示,无权限,则不显示
创建service:
创建一个函数,返回Observable
import { Injectable } from '@angular/core'; import { AuthService } from './auth.service'; import { ApiAuth } from '../apis'; import { UserInfo } from '../model'; import { Observable} from 'rxjs/Rx';
@ Injectable() exportclassRoleService { roles : Array<any>; userinfo : UserInfo; getUserTime :number; // 调用接口时,记录一下时间点 expiredTime = 1000 * 60 * 5; // 过期时间
constructor( privateauthService: AuthService, privateapiAuth: ApiAuth) { }
getRoles() : Observable<any> { letuserInfo$; constuserEmail = this.authService. getUserEmail(); if ( ! this.userinfo ||Date. now() > this.getUserTime + this.expiredTime) { userInfo$ = this.apiAuth. getUserInfo(userEmail). map(res=>{ this.getUserTime =Date. now(); return this.userinfo = res as UserInfo; }) // 请求失败时,抛出异常 . catch( this.handleError); } else { // 创建一个新Observable,不然还会去重新调用接口 userInfo$ = Observable. create(serve=>{ serve. next( this.userinfo); serve. complete(); }); } // 返回的是 Observable 对象 return userInfo$; }
private handleError(error:any) { consterrMsg = (error.message) ? error.message : error.status ? ` ${error.status } - ${error.statusText } ` : 'Server error'; console. error(errMsg); return Observable. throw(errMsg); }
}
自定义directive(改写ngIf)
import { Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, OnDestroy } from '@angular/core'; import { RoleService } from '../service/role.service'; import { UserInfo } from '../model';
@ Directive({ selector: '[appRole]' }) exportclassRoleDirective implementsOnDestroy{ private _context : RoleContext = new RoleContext(); private _thenTemplateRef : TemplateRef< RoleContext> |null= null; private _elseTemplateRef : TemplateRef< RoleContext> |null= null; private _thenViewRef : EmbeddedViewRef< RoleContext> |null= null; private _elseViewRef : EmbeddedViewRef< RoleContext> |null= null;
userRoles : Array<string>; isShow :boolean; userInfo$;
constructor( private_viewContainer: ViewContainerRef, templateRef: TemplateRef< RoleContext>, privateroleService: RoleService) { this._thenTemplateRef = templateRef; }
@ Input() setappRole(condition:any) { this._context.$implicit = this._context.ngIf = condition; this. testRole( this._context.$implicit, ()=>{ this. _updateView(); }); }
@ Input() setappRoleThen(templateRef: TemplateRef< RoleContext>) { this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this. testRole( this._context.$implicit, ()=>{ this. _updateView(); }); }
@ Input() setappRoleElse(templateRef: TemplateRef< RoleContext>) { this._elseTemplateRef = templateRef; this._elseViewRef = null; // clear previous view if any. this. testRole( this._context.$implicit, ()=>{ this. _updateView(); }); }
private _updateView() { if ( this.isShow) { if ( ! this._thenViewRef) { this._viewContainer. clear(); this._elseViewRef = null; if ( this._thenTemplateRef) { this._thenViewRef = this._viewContainer. createEmbeddedView( this._thenTemplateRef, this._context); } } } else { if ( ! this._elseViewRef) { this._viewContainer. clear(); this._thenViewRef = null; if ( this._elseTemplateRef) { this._elseViewRef = this._viewContainer. createEmbeddedView( this._elseTemplateRef, this._context); } } } }
private testRole(roles,callback) { this.userInfo$ = this.roleService. getRoles(). subscribe(res=>{ this.userRoles = res.features; this.isShow = true; roles. forEach(r=>{ if ( ! this.userRoles. includes(r)) { this.isShow = false; return; } }); return callback(); }, error=>{ this.isShow = false; return callback(); }); }
ngOnDestroy() { this.userInfo$. unsubscribe(); }
}
exportclassRoleContext { public $implicit :any= null; public ngIf :any= null; }
分为结构指令和属性指令
TempalteRef & ViewContainerRef 和 ElementRef
结构指令如果返回false会阻断后续操作,会比较好一些
当前指令和ngIf的区别:
获取的是权限的一个数组,不是一个true或者false参数
参考文章:
/a/1190000009674089#articleHeader17
/a/1190000009499160
/a/1190000008672478
/a/1190000009307714#articleHeader5
/a/1190000008653690
/a/1190000008626070
/a/1190000008695459
知识点:
angular service
angular directive(结构指令、属性指令)
angular 组件和指令的生命周期点击打开链接
学习ngIf源码
Rxjs原理
Rxjs的Observable
教程1
教程2
教程3
优化:
使用RxJs改写:
注意事项:
1. 注意处理异常
2. 注意请求的间隔时间
3. 要在自定义组件的生命周期结束之后,销毁流
4. 有数据时,并且在有效期内,不去重新请求
优化之前的代码(这种方式不好,仅作为记录)
service:
import { Injectable } from '@angular/core'; import { AuthService } from './auth.service'; import { ApiAuth } from '../apis'; import { UserInfo } from '../model';
@ Injectable() exportclassRoleService { roles : Array<any>; userinfo : UserInfo;
constructor( privateauthService: AuthService, privateapiAuth: ApiAuth) { }
getRoles(callback) { constuserEmail = this.authService. getUserEmail(); this.apiAuth. getUserInfo(userEmail). subscribe(res=>{ this.userinfo = res as UserInfo; return callback( this.userinfo); }); }
}
directive:
import { Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef } from '@angular/core'; import { RoleService } from '../service/role.service'; import { UserInfo } from '../model';
@ Directive({ selector: '[appRole]' }) exportclassRoleDirective { private _context : RoleContext = new RoleContext(); private _thenTemplateRef : TemplateRef< RoleContext> |null= null; private _elseTemplateRef : TemplateRef< RoleContext> |null= null; private _thenViewRef : EmbeddedViewRef< RoleContext> |null= null; private _elseViewRef : EmbeddedViewRef< RoleContext> |null= null;
userRoles : Array<string>; isShow :boolean;
constructor( private_viewContainer: ViewContainerRef, templateRef: TemplateRef< RoleContext>, privateroleService: RoleService) { this._thenTemplateRef = templateRef; }
@ Input() setappRole(condition:any) { this._context.$implicit = this._context.ngIf = condition; this. testRole( this._context.$implicit, ()=>{ this. _updateView(); }); }
@ Input() setappRoleThen(templateRef: TemplateRef< RoleContext>) { this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this. testRole( this._context.$implicit, ()=>{ this. _updateView(); }); }
@ Input() setappRoleElse(templateRef: TemplateRef< RoleContext>) { this._elseTemplateRef = templateRef; this._elseViewRef = null; // clear previous view if any. this. testRole( this._context.$implicit, ()=>{ this. _updateView(); }); }
private _updateView() { if ( this.isShow) { if ( ! this._thenViewRef) { this._viewContainer. clear(); this._elseViewRef = null; if ( this._thenTemplateRef) { this._thenViewRef = this._viewContainer. createEmbeddedView( this._thenTemplateRef, this._context); } } } else { if ( ! this._elseViewRef) { this._viewContainer. clear(); this._thenViewRef = null; if ( this._elseTemplateRef) { this._elseViewRef = this._viewContainer. createEmbeddedView( this._elseTemplateRef, this._context); } } } }
private testRole(roles,callback) { this.roleService. getRoles((data: UserInfo)=>{ this.userRoles = data.features;
this.isShow = true; roles. forEach(r=>{ if ( ! this.userRoles. includes(r)) { this.isShow = false; return; } }); return callback(); }); }
}
exportclassRoleContext { public $implicit :any= null; public ngIf :any= null; }