为什么在评估函数时会将输入属性调用数百次

时间:2018-06-06 12:49:55

标签: javascript angular forms typescript disabled-input

我通过控制访问使用属性来检查是否应启用或禁用字段。

所以我有这样的事情:

<input matInput type="text" #name="ngModel" name="application.name" [ngModel]="application?.name" (ngModelChange)="application.name=$event"
              placeholder="Nom de l'application" required [disabled]="isDisabled([permissions.applications.any.update, permissions.applications.own.update], 'name')"[appUnique]="application" [listElem]="applications" key="name" maxlength="255">

当显示输入时,isDisabled函数会被调用数百次,并且表单上的每个操作都会触发12或32次额外调用。

这导致我的浏览器冻结。

知道为什么会发生这种行为吗?是ZoneJS引起了这个吗?

如何只调用一个这个函数?

编辑:指令实施

/**
 * Check if the component should be disabled
 */
@Directive({
  selector: "[appIsDisabled]"
})
export class IsDisabledDirective implements OnInit {
  // Listof permission to check 
  @Input("appIsDisabled") permissions: PermissionInterface[];
  // The resource id to be access
  @Input() resourceId: number;
  // The resource type to be access
  @Input() resourceType: string;
   // Attribute to be check(eg: name, firstname... for a user resource)
  @Input() attribute: string;
  constructor(private authService: AuthService, private el: ElementRef, private utilsService: UtilsService, private renderer: Renderer2) {
  }

  ngOnInit() {
    if (!this.authService.hasPermission(this.permissions, this.resourceId, this.resourceType, this.attribute)) {
      this.renderer.setAttribute(this.el.nativeElement, "disabled", "disabled");
    }

  }
}

3 个答案:

答案 0 :(得分:1)

最好不要对方法进行属性绑定,以避免过于频繁地检查状态。

以下是我的建议:

  1. 使用 RxJS 跟踪更改。
    • 尝试检测 permissions.applications.any.update 更改并将其包装到Observable中。您可以从组件中的ngOnInit挂钩订阅。
  2. 使用 Pure Pipe 检测更改。
    • 尝试将isDisabled方法移动到纯管道组件。
  3. 使用 setInterval 定期检查状态更改。

答案 1 :(得分:0)

简短的回答是你的方法是由角度变化检测算法执行的。 Angular会扫描每个绑定以检测更改并相应地执行操作,并且它会相当频繁地执行,并且每个单个事件可能会发生多次。您需要了解this process以及如何minimize it。这是一个很大的主题,在SO答案中详细说明是不合适的,但参考文章中的三个提示是:

  

拥有更少的DOM。这是一个至关重要的难题。如果DOM元素不可见,则应使用* ngIf将其从DOM中删除,而不是简单地使用CSS隐藏元素。俗话说,最快的代码是没有运行的代码 - 最快的DOM是不存在的DOM。

     

让你的表情更快。将复杂计算移动到ngDoCheck生命周期钩子中,并参考视图中的计算值。尽可能将结果缓存到复杂的计算中。

     

使用OnPush更改检测策略告诉Angular 2没有任何更改。这使您可以在大多数时间内跳过大部分应用程序的整个更改检测步骤。

答案 2 :(得分:0)

好的,我找到了解决问题的方法, 我预先计算组件侧所有字段的状态。 因此,对于用户配置文件,这是我的功能:

 computesFieldsDisableState() {
    this.disabled = {
      thumbnails: !this.authService.hasPermission([this.permissions.profil.update], this.user.id, "user", "thumbnails"),
      name: !this.authService.hasPermission([this.permissions.profil.update], this.user.id, "user", "name"),
      firstname: !this.authService.hasPermission([this.permissions.profil.update], this.user.id, "user", "firstname"),
      password: !this.authService.hasPermission([this.permissions.profil.update], this.user.id, "user", "password"),
      email: !this.authService.hasPermission([this.permissions.profil.update], this.user.id, "user", "email"),
      roles: !this.authService.hasPermission([this.permissions.profil.update], this.user.id, "user", "roles"),
    };
  }

现在我只需使用[disabled]="disabled.thumbnails"来获取该字段的状态。

谢谢大家的答案。