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 进入该组件。
我在尝试按 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 进入该组件。