You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular结构指令多输入:首加载时第二个参数值无法在第一个Input中获取

Angular结构指令多参数读取问题

问题详情

我创建了一个支持多参数的Angular结构指令,目前遇到问题:第二个参数的值无法在accessControlRole这个@Input中读取,但该值在自身的@Input(accessControlRolePermission)中是存在的。请问这是什么原因,以及如何在accessControlRole中获取该参数值?

指令代码

@Directive({
  selector: '[accessControlRole]'
})
export class AccessControlRoleDirective implements OnInit {
  userProfile!: UserProfile;
  private _accessControlRolePermission!:string;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef,
    private jwtAuthService: JwtAuthService,
    ) {
  }

  ngOnInit(): void {
  }

  @Input() set accessControlRole(roleAllowed: Permission[]) {
    this.jwtAuthService.user.subscribe(user => {
      if (user&&this._accessControlRolePermission) {
        this.userProfile = user;
        if(this._accessControlRolePermission === 'Approve'){
          console.log('yesssssssssssssssssssssss');
          this.viewContainerRef.createEmbeddedView(this.templateRef);
        }
      }
      else{
        console.log("_accessControlRolePermission value is empty");
      }
    });
  }

  @Input() set accessControlRolePermission(permission:string) {
    this._accessControlRolePermission = permission;
    console.log('accessControlRolePermission value::::',this._accessControlRolePermission);
  }
}

组件调用方式

<ng-container *accessControlRole="this.userPermissionRoles;permission:'Approve'">
         <a class="btn btn-lg btn-success btn-block">Approve</a>
</ng-container>

控制台输出

  • _accessControlRolePermission value is empty
  • accessControlRolePermission value:::: Approve

原因分析

Angular对结构指令多参数输入属性的赋值顺序没有固定保证,你的代码中accessControlRole的setter可能先于accessControlRolePermission的setter执行,导致此时_accessControlRolePermission还未被赋值,所以会输出空值提示。

另外,accessControlRole的setter中直接订阅user流却未处理订阅清理,会导致重复订阅和内存泄漏问题。


解决方案

方案1:合并参数为对象传递

将多个参数合并成一个对象,确保所有参数同时被接收:

修改指令输入:

@Input() set accessControlRole(options: { roles: Permission[], permission: string }) {
  this.jwtAuthService.user.subscribe(user => {
    if (user && options.permission) {
      this.userProfile = user;
      if(options.permission === 'Approve'){
        console.log('yesssssssssssssssssssssss');
        this.viewContainerRef.createEmbeddedView(this.templateRef);
      } else {
        this.viewContainerRef.clear();
      }
    } else {
      console.log("_accessControlRolePermission value is empty");
      this.viewContainerRef.clear();
    }
  });
}

组件调用修改为:

<ng-container *accessControlRole="{ roles: this.userPermissionRoles, permission: 'Approve' }">
         <a class="btn btn-lg btn-success btn-block">Approve</a>
</ng-container>

方案2:通过ngOnChanges等待所有参数就绪

利用ngOnChanges生命周期钩子,监听所有输入属性变化,待必要参数都赋值完成后再执行逻辑,同时处理订阅清理:

修改指令代码:

import { Directive, TemplateRef, ViewContainerRef, Input, OnChanges, SimpleChanges, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

@Directive({
  selector: '[accessControlRole]'
})
export class AccessControlRoleDirective implements OnChanges, OnDestroy {
  userProfile!: UserProfile;
  @Input() accessControlRole!: Permission[];
  @Input() accessControlRolePermission!: string;
  private userSubscription?: Subscription;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef,
    private jwtAuthService: JwtAuthService,
  ) {
  }

  ngOnChanges(changes: SimpleChanges): void {
    // 检查所有必要参数是否已赋值
    if (this.accessControlRole && this.accessControlRolePermission) {
      this.checkPermission();
    }
  }

  ngOnDestroy(): void {
    // 清理订阅,防止内存泄漏
    this.userSubscription?.unsubscribe();
  }

  private checkPermission(): void {
    // 先清理旧订阅
    this.userSubscription?.unsubscribe();
    this.userSubscription = this.jwtAuthService.user.subscribe(user => {
      if (user && this.accessControlRolePermission) {
        this.userProfile = user;
        if(this.accessControlRolePermission === 'Approve'){
          console.log('yesssssssssssssssssssssss');
          this.viewContainerRef.createEmbeddedView(this.templateRef);
        } else {
          this.viewContainerRef.clear();
        }
      } else {
        console.log("_accessControlRolePermission value is empty");
        this.viewContainerRef.clear();
      }
    });
  }
}

组件调用保持原有方式即可:

<ng-container *accessControlRole="this.userPermissionRoles;permission:'Approve'">
         <a class="btn btn-lg btn-success btn-block">Approve</a>
</ng-container>

方案说明

  • 方案1简洁直观,适合参数较少的场景;
  • 方案2更灵活,支持单独监听每个参数的变化,同时解决了RxJS订阅泄漏的问题;
  • 无论选择哪种方案,都必须在组件销毁时清理RxJS订阅,避免内存泄漏。

内容的提问来源于stack exchange,提问作者ZAJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 05:43:16