【问题标题】:Angular 8 add class after page load Error: ExpressionChangedAfterItHasBeenCheckedErrorAngular 8在页面加载错误后添加类:ExpressionChangedAfterItHasBeenCheckedError
【发布时间】:2020-03-17 02:36:36
【问题描述】:

正如标题所示,我正在尝试在页面加载后向div 元素添加一个类!我有一个条件isTrue,并且在页面加载后执行的角度函数ngAfterViewInit() 使isTrue 的值成为true,然后添加类hideOnLoad。当然我可以使用标准的javascriptjquery,但我必须以有角度的方式来做。本质上,最终结果应该是,div.index-logo-wrapper 在页面加载后慢慢淡出。我的想法是在加载后添加一个类,逐渐减少opacity 您的输入非常感谢。

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-index-section',
  templateUrl: './index-section.component.html',
  styleUrls: ['./index-section.component.scss']
})
export class IndexSectionComponent implements OnInit {
  isTrue: boolean = false;
  public innerWidth: any;
  constructor() { }

  ngOnInit() {
  }

  ngAfterViewInit() {
    this.innerWidth = window.innerWidth;
    if (this.innerWidth < 1000) {
      this.isTrue = true;
      alert(this.isTrue);
    }
  }
}
<section class="index-section">
  <div class="index-logo-wrapper" [class.hideOnLoad]="isTrue">
    <figure>
      <img src="assets/icons/logo_mobile.svg" alt=" logo">
    </figure>
  </div>
  <div class="index-media-wrapper">
    <div class="media-container">
      <iframe src="https://player.vimeo.com/video/128014070?autoplay=1&color=ffffff&title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Itaque contra est, ac dicitis; Duo Reges: constructio interrete. Videsne quam sit magna dissensio?
      </p>
    </div>
  </div>
</section>

这是我控制台中的错误:

【问题讨论】:

    标签: javascript html angular angular8


    【解决方案1】:

    您不应该更改与 Angular 挂钩中的绑定相关的内容,因为这会干扰更改检测过程。将变更检测视为绞肉机。您应该只尝试在进肉之前或出肉之后换肉——您不能在过程中间改变它。

    你可以做的是把它变成一个 RxJs 流,并在模板中与async 管道一起使用。这样 Angular 就会在更改检测期间知道某些内容发生了更改,并在完成后重新触发它。

    或者你可以注入ChangeDetectorRefthis.changeDetectorRef.markForCheck() 在你改变了与生命周期钩子中的绑定相关的地方。对于您的情况,它实际上与 async 管道相同。

    这是更一般的建议,这是针对您的特定情况的解决方案,它也适用于 Angular Universal(服务器端渲染):

    import { DOCUMENT } from '@angular/common';
    import { Component, Inject, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-index-section',
      templateUrl: './index-section.component.html',
      styleUrls: ['./index-section.component.scss']
    })
    export class IndexSectionComponent {
      readonly isTrue: boolean;
    
      constructor(@Inject(DOCUMENT) {defaultView}: Document) {
        this.isTrue = !defaultView || defaultView.innerWidth < 1000;
      }
    }
    
    

    当然,服务器上不会有窗口大小,但是访问window 上的属性可能会导致该环境中的错误,最好不要直接在您的 Angular 应用程序中使用 DOM API,而是通过令牌使用抽象。

    【讨论】:

    • 感谢您的意见!从概念上讲,这是有道理的,绞肉机就是一个很好的例子!现在我只需要弄清楚如何在我的情况下实现它......
    • 我对自己想做的事情的态度是否有意义?
    • 在您的情况下,我要做的是创建一个只读属性并在构造函数中分配它。也就是说,如果你只想设置一次。
    • 更新了我的答案。如果你想要这种动态,你可以从窗口上的 resize 事件创建一个 observable 并将其与async 管道一起使用。这样,您还可以添加限制,以免影响快速调整大小事件的性能。
    【解决方案2】:

    正如其他人所说,您可以使用以下解决方案:

    <div class="index-logo-wrapper" [ngClass]="isTrue ? 'hideOnLoad' : ''">
    

    但是当它用于单个类时,我更喜欢这种其他语法:

    <div class="index-logo-wrapper" [class.hideOnLoad]="isTrue">
    

    它更容易阅读和清洁。

    【讨论】:

    • 是的,我更喜欢使用第二种语法(就像使用的那样),问题是它不起作用!我的代码和你的一样,问题是我做错了什么?
    【解决方案3】:

    您可以通过任一方式动态添加类

    &lt;div class="index-logo-wrapper" [ngClass]="{'hideOnLoad':isTrue}"&gt;

    &lt;div class="index-logo-wrapper  {{isTrue ? 'hideOnLoad' : ''}}"&gt;

    【讨论】:

    • 第二个无效。
    • 两者都适合我。不知道你出了什么问题@AntoineB
    【解决方案4】:

    您可以使用三元运算符? 动态添加类。如果isTrue则添加hideOnLoad,否则类为空:

    <div class="index-logo-wrapper" [ngClass]="isTrue ? 'hideOnLoad' : ''">
    

    【讨论】:

      猜你喜欢
      • 2020-03-18
      • 2021-06-12
      • 1970-01-01
      • 2020-04-09
      • 1970-01-01
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多