1. 程式人生 > >angular 許可權控制 service+ 自定義指令(改寫ngIf)

angular 許可權控制 service+ 自定義指令(改寫ngIf)

功能說明:許可權控制

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()export class RoleService { roles: Array<any>; userinfo: UserInfo; getUserTime: number; // 呼叫介面時,記錄一下時間點 expiredTime = 1000 * 60 * 5; // 過期時間
constructor(private authService: AuthService, private apiAuth: ApiAuth) { }
getRoles(): Observable
<any> { let userInfo$; const userEmail = 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) { const errMsg = (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]'})export class RoleDirective implements OnDestroy { 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>, private roleService: RoleService) { this._thenTemplateRef = templateRef; }
@Input() set appRole(condition: any) { this._context.$implicit = this._context.ngIf = condition; this.testRole(this._context.$implicit, () => { this._updateView(); }); }
@Input() set appRoleThen(templateRef: TemplateRef<RoleContext>) { this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this.testRole(this._context.$implicit, () => { this._updateView(); }); }
@Input() set appRoleElse(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(); }
}
export class RoleContext { public $implicit: any = null; public ngIf: any = null;}

分為結構指令和屬性指令

TempalteRef & ViewContainerRef 和 ElementRef

結構指令如果返回false會阻斷後續操作,會比較好一些

當前指令和ngIf的區別:

獲取的是許可權的一個數組,不是一個true或者false引數

參考文章:

https://segmentfault.com/a/1190000009674089#articleHeader17

https://segmentfault.com/a/1190000009499160

https://segmentfault.com/a/1190000008672478

https://segmentfault.com/a/1190000009307714#articleHeader5

https://segmentfault.com/a/1190000008653690

https://segmentfault.com/a/1190000008626070

https://segmentfault.com/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()export class RoleService { roles: Array<any>; userinfo: UserInfo;
constructor(private authService: AuthService, private apiAuth: ApiAuth) { }
getRoles(callback) { const userEmail = 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]'})export class RoleDirective { 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>, private roleService: RoleService) { this._thenTemplateRef = templateRef; }
@Input() set appRole(condition: any) { this._context.$implicit = this._context.ngIf = condition; this.testRole(this._context.$implicit, () => { this._updateView(); }); }
@Input() set appRoleThen(templateRef: TemplateRef<RoleContext>) { this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this.testRole(this._context.$implicit, () => { this._updateView(); }); }
@Input() set appRoleElse(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(); }); }
}
export class RoleContext { public $implicit: any = null; public ngIf: any = null;}