Angular 2 修复动态Particles JS Cannot read 属性 'getElementsByClassName' of null

Angular 2 Fix dynamic Particles JS Cannot read property 'getElementsByClassName' of null

我正在使用 angular 2 v4 开发 Web 应用程序,我想使用参数动态包含不同的 Particles.js 我想加载特定的粒子格式。

问题是这个参数来自数据库,我通过 observables 管理它,因此不可能从 ngOnInit 函数或构造函数加载它。

一切正常并正确加载文档,问题是当我离开那条路线时出现错误:

Cannot read property 'getElementsByClassName' of null

这里有我的一些配置

angular-cli.json

"scripts": [
        ...
        "../node_modules/particles.js/particles.js",
        ...
      ],

login.ts

declare var particlesJS: any;
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
// Color variables----------------------------------------------------
    default = false;
    amber = false;
    green = false;
    red = false;
    blue = false;
    gray = false;
    white = false;
    purple = false;
    orange = false;
    lightBlue = false;
  // Color variables----------------------------------------------------

  clientConfig: any;
  constructor(public clientConfigService: ClientConfigService) {
        this.clientConfigService.readData().subscribe(data => {
          this.clientConfig = data;
          this.changeTheme(this.clientConfig);
        } );
      }
  ngOnInit() {}

  changeTheme(config: Client) {
    this.default = false;
    this.amber = false;
    this.green = false;
    this.red = false;
    this.blue = false;
    this.gray = false;
    this.white = false;
    this.purple = false;
    this.orange = false;
    this.lightBlue = false;
    switch (config.color) {
      case 'default': this.default = true; particlesJS.load('particles-js', 'assets/data/default-particles.json'); break;
      case 'amber': this.amber = true; particlesJS.load('particles-js', 'assets/data/amber-particles.json'); break;
      case 'green': this.green = true; particlesJS.load('particles-js', 'assets/data/green-particles.json'); break;
      case 'red': this.red = true; particlesJS.load('particles-js', 'assets/data/red-particles.json'); break;
      case 'blue': this.blue = true; particlesJS.load('particles-js', 'assets/data/blue-particles.json'); break;
      case 'gray': this.gray = true; particlesJS.load('particles-js', 'assets/data/gray-particles.json'); break;
      case 'white': this.white = true; particlesJS.load('particles-js', 'assets/data/white-particles.json'); break;
      case 'purple': this.purple = true; particlesJS.load('particles-js', 'assets/data/purple-particles.json'); break;
      case 'orange': this.orange = true; particlesJS.load('particles-js', 'assets/data/orange-particles.json'); break;
      case 'lightblue': this.lightBlue = true; particlesJS.load('particles-js', 'assets/data/light-blue-particles.json'); break;
      default: this.default = true; particlesJS.load('particles-js', 'assets/data/default-particles.json'); break;
    }
  }
}

login.html

<div id="particles-js"></div>

此路由属于 "localhost:4200/login",此时,一切正常,控制台中没有错误。问题是当我去另一条路线时 "localhost:4200/forgot" 例如(或任何其他)。就在我去其他路线的时候,这个错误出现在控制台:

ERROR TypeError: Cannot read property 'getElementsByClassName' of null
    at window.particlesJS (scripts.bundle.js:4114)
    at XMLHttpRequest.xhr.onreadystatechange (scripts.bundle.js:4150)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
    at Object.onInvoke (core.es5.js:3890)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runGuarded (zone.js:161)
    at XMLHttpRequest.<anonymous> (zone.js:144)



更新

这是我所有的 HTML 代码,包括路由。此页面显示在路线 http://localhost:4200/session/signin

因此,当我单击登录按钮并转到任何其他路径(在本例中为 http://localhost:4200/dashboard)并且基本组件被销毁时...控制台显示错误

路由选择

export const AppRoutes: Routes = [
{
  path: '', component: AdminLayoutComponent,
  canActivate: [AuthGuard], children: [{ path: 'dashboard',  loadChildren: './dashboard/dashboard.module#DashboardModule' }]
},
{
  path: '',
  component: AuthLayoutComponent,
  children: [{
    path: 'session',
    loadChildren: './session/session.module#SessionModule'
  }]
}];

Login.html

<div class="whitemask">
    <div id="particles-js" fxLayout="column" fxLayoutAlign="center center" class=" gradient-animated">
      <div class="session-wrapper" style="position: absolute;">

        <div class="mat-card-login">
          <div class="login-form">
            <form [formGroup]="form" (ngSubmit)="onSubmit()" autocomplete="off">
              <div fxLayout="column" fxLayoutAlign="space-around">
                <div class="pb-1">
                  <mat-form-field color="accent" class="login-input" style="width: 100%">
                    <input name="i-sl-li-lg-001" matInput placeholder="Cuenta"  [formControl]="form.controls['account']">
                    <mat-error *ngIf="form.controls['account'].hasError('required') && form.controls['account'].touched" class="mat-text-warn">Debe ingresar una cuenta válida.</mat-error>
                  </mat-form-field>
                </div>
                <div class="pb-1">
                  <mat-form-field color="accent" class="login-input" style="width: 100%">
                    <input name="i-sl-li-lg-003" matInput color="accent" [type]="passvisible" placeholder="Contraseña" [formControl]="form.controls['password']">
                    <mat-icon matSuffix (click)="visibePass()" style="cursor: pointer" [ngStyle]="{ 'color': passvisible === 'password' ? 'rgba(0,0,0,0.44)' : 'black' }">visibility</mat-icon>
                    <mat-error *ngIf="form.controls['password'].hasError('required') && form.controls['password'].touched" class="mat-text-warn">Debe ingresar una contraseña.</mat-error>
                  </mat-form-field>
                </div>
                <div *ngIf="showMessage" fxLayout="row" fxLayoutAlign="center center" class="errortext" style="margin-bottom: 10px; margin-top: -15px">{{ error }}</div>
                <button id="b152" mat-raised-button class="login-button" type="submit" [disabled]="!form.valid">Iniciar sesión</button>

                <div style="padding-top: 10px" fxLayout="row" fxLayoutAlign="center center">
                    <a class="forgot" [routerLink]="['/session/forgot']">¿Olvidaste tu contraseña?</a>
                </div>
              </div>
            </form>
          </div>
        </div>

      </div>
    </div>
  </div>

Login.ts 提交时的功能

onSubmit() {
    this.authService.login(this.form.controls['account'].value,
                           this.form.controls['password'].value).subscribe(
      data => {
        if (data.access_token) {
          this.router.navigate(['/dashboard']);
          this.showMessage = false;
        } else {
          if (data.status) {
            switch (data.status) {
              case '401': this.error = 'Error'; break;
              case '402': this.error = 'User nor found'; break;
            }
          }
        }
      },
      error => {
        this.error = 'Login Error, try it later.';
      });
  }

通过将您的代码移到 ngAfterViewInit 结构中再试一次。

declare var particlesJS: any;
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit, AfterViewInit {
// Color variables----------------------------------------------------
    default = false;
    amber = false;
    green = false;
    red = false;
    blue = false;
    gray = false;
    white = false;
    purple = false;
    orange = false;
    lightBlue = false;
  // Color variables----------------------------------------------------

  clientConfig: any;
  constructor(public clientConfigService: ClientConfigService) {

  }

  ngOnInit() {}

  ngAfterViewInit() {
       this.clientConfigService.readData().subscribe(data => {
          this.clientConfig = data;
          this.changeTheme(this.clientConfig);
        } );
  }

  changeTheme(config: Client) {
    this.default = false;
    this.amber = false;
    this.green = false;
    this.red = false;
    this.blue = false;
    this.gray = false;
    this.white = false;
    this.purple = false;
    this.orange = false;
    this.lightBlue = false;
    switch (config.color) {
      case 'default': this.default = true; particlesJS.load('particles-js', 'assets/data/default-particles.json'); break;
      case 'amber': this.amber = true; particlesJS.load('particles-js', 'assets/data/amber-particles.json'); break;
      case 'green': this.green = true; particlesJS.load('particles-js', 'assets/data/green-particles.json'); break;
      case 'red': this.red = true; particlesJS.load('particles-js', 'assets/data/red-particles.json'); break;
      case 'blue': this.blue = true; particlesJS.load('particles-js', 'assets/data/blue-particles.json'); break;
      case 'gray': this.gray = true; particlesJS.load('particles-js', 'assets/data/gray-particles.json'); break;
      case 'white': this.white = true; particlesJS.load('particles-js', 'assets/data/white-particles.json'); break;
      case 'purple': this.purple = true; particlesJS.load('particles-js', 'assets/data/purple-particles.json'); break;
      case 'orange': this.orange = true; particlesJS.load('particles-js', 'assets/data/orange-particles.json'); break;
      case 'lightblue': this.lightBlue = true; particlesJS.load('particles-js', 'assets/data/light-blue-particles.json'); break;
      default: this.default = true; particlesJS.load('particles-js', 'assets/data/default-particles.json'); break;
    }
  }
}

您收到此错误是因为 particles.js 试图访问的 html 元素尚未生成。请查看 this document 了解更多信息。