Angular - 如何在使用 ViewEncapsulation.Native 时访问 html 元素

Angular - How to access html element while using ViewEncapsulation.Native

我在尝试按 ID 访问 html 元素时遇到以下错误。当用户单击按钮以将不同样式 class 应用于元素时,我试图访问 classList。 class 列表和元素通常始终为空,除非我将 viewEncapsulation 切换回默认模拟设置。

错误消息

TypeError: Cannot read property 'classList' of null

问题: 我试图让这个特定组件不继承我通过 angular.json 文件导入到项目中的第 3 方 SCSS 文件。当我使用默认 ViewEncapsulation.Emulated 时,该组件继承了与某些组件样式冲突的全局 SCSS 样式。

文件结构正常,我是把SCSS和HTML放在对应的文件里,然后导入到组件中。

我觉得这应该是大型项目的常见主题。如果有不同的方法来切换事件元素的样式,请告诉我。

组件.ts:

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

@Component({
  encapsulation: ViewEncapsulation.Native,
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'scssTesting';

  constructor() { }

  step: string = 'step1';

  step1: any;
  step2: any;
  step3: any;


  ngOnInit() {

  }

  next() {

    this.step1 = document.getElementById('step1');
    this.step2 = document.getElementById('step2');
    this.step3 = document.getElementById('step3');


    if (this.step === 'step1') {
      this.step = 'step2';
      this.step1.classList.remove("is-active");
      this.step1.classList.add("is-complete");
      this.step2.classList.add("is-active");

    } else if (this.step === 'step2') {
        ....
  }
}

组件.scss

.progress {
  position: relative;
  display: flex;
  .........
}

组件 .html

<div class="container">
    <div class="progress">
        <div class="progress-track"></div>
        <div id="step1" class="progress-step">
            Step One
        </div>
        <div id="step2" class="progress-step">
            Step Two
        </div>
        <div id="step3" class="progress-step">
            Step Three
        </div>
    </div>
    <button (click)="next()">Next Step</button>
</div>

我能想到的访问 HTML 元素的最简单方法是使用 Angulars ElementRef。您可以阅读更多相关内容 here请谨慎使用! 下面是一个关于如何在您的案例中使用它的示例:

在你的app.component.html

<div #myelement>This is Pink</div>

在你的app.component.ts

import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  @ViewChild('myelement') el: ElementRef;

  ngAfterViewInit() {
    this.el.nativeElement.classList.add("myclass");
  }
}

在你的app.component.css

.myclass {
    color: pink;
    font-weight: bold;
}

编辑:

对于纯样式,正如@SnorreDan 已经提到的,最好使用 Angulars [ngClass] 指令。您可以通过以下示例了解如何执行此操作:

在你的app.component.html

<div [ngClass]="myColorClass">This may change color!</div>

<button (click)="makePink()">Pink</button>
<button (click)="makeGreen()">Green</button>

在你的app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  myColorClass: string

  makePink() {
    this.myColorClass = 'pink';
  }

  makeGreen() {
    this.myColorClass = 'green';
  }
}

在你的app.component.css

.pink {
    color: pink;
    font-weight: bold;
}

.green {
    color: green;
    font-weight: bold;
}

希望对您有所帮助!

我认为您在问两个不同的问题:

1.如何在Angular:

中动态添加和删除classes

在Angular中你应该尽量避免直接使用document。根据条件添加 class 的一个好方法是使用 ngClass 指令,您可以在此处阅读更多相关信息:https://angular.io/guide/template-syntax#ngclass

另一种动态添加 class 的方法是使用 ViewChild 从模板中获取元素,然后使用 angular 渲染器在元素上设置 class(您会发现更多信息,如果你 google 它)

2。如何让我的组件不从 Angular.json 文件

继承全局 CSS

我想不出解决办法。使用像 ViewEncapsulation.None 和 ViewEncapsulation.Emulated 这样的封装策略不会解决这个问题,因为它们只会影响这个组件中的 classes 而不会传播到其他组件。它不影响全局 [​​=34=]es 进入该组件。