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



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Angular 中,你可以通过自定义指令来扩展 HTML 元素的行为和功能。下面是自定义指令的基本步骤: 1. 创建指令类: - 创建一个新的类,用于定义你的指令。 - 使用 `@Directive` 装饰器来标记该类为一个指令,并传入一个配置对象。 下面是一个示例: ```typescript import { Directive, ElementRef } from '@angular/core'; @Directive({ selector: '[appCustomDirective]' }) export class CustomDirective { constructor(private elementRef: ElementRef) { this.elementRef.nativeElement.style.backgroundColor = 'yellow'; } } ``` 在上面的示例中,我们创建了一个名为 `CustomDirective` 的指令类,并使用 `@Directive` 装饰器来标记它为一个指令。`selector` 属性指定了该指令在模板中的使用方式,这里使用的是属性选择器 `[appCustomDirective]`。 2. 在模板中应用指令: - 在需要应用指令的元素上使用指令的选择器,可以是属性选择器、类选择器或标签选择器。 下面是一个示例: ```html <div appCustomDirective>Custom Directive Example</div> ``` 在上面的示例中,我们使用 `[appCustomDirective]` 属性选择器将自定义指令应用到了 `<div>` 元素上。 3. 使用指令提供的功能: - 在指令类中可以定义各种功能,如修改元素样式、监听事件、操作 DOM 等。 - 在构造函数中可以注入依赖,如 `ElementRef` 用于操作元素。 在上面的示例中,我们在指令类的构造函数中注入了 `ElementRef`,使用它来获取指令所应用的元素,并修改其背景颜色为黄色。 通过以上步骤,你就可以创建和使用自定义指令了。可以根据需求在指令类中实现各种功能,并在模板中应用指令来扩展元素的行为和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值