angular - 了解 Angular 中的作用域
问题描述
我对角度很陌生,所以我希望这个问题不是太基本。我正在尝试以角度运行一个函数,但我的变量范围似乎存在问题。这是它的样子:
export class Skulder14q1Component {
button1 = document.getElementById('button1');
button2 = document.getElementById('button2');
button3 = document.getElementById('button3');
button4 = document.getElementById('button4');
showallbutton = document.getElementById('showallbutton');
onShowAllOptions() {
this.button1.classList.toggle('hide');
this.button2.classList.toggle('hide');
this.button3.classList.toggle('hide');
this.button4.classList.toggle('hide');
this.showallbutton.classList.add('hide');
}
现在该功能通过按下按钮运行,但是当按下按钮时,控制台日志返回:
> Skulder14q1Component.html:12 ERROR TypeError: Cannot read property 'classList' of null
at Skulder14q1Component.onShowAllOptions (skulder14q1.component.ts:28)
at Object.eval [as handleEvent] (Skulder14q1Component.html:15)
at handleEvent (core.js:10251)
at callWithDebugContext (core.js:11344)
at Object.debugHandleEvent [as handleEvent] (core.js:11047)
at dispatchEvent (core.js:7710)
at core.js:8154
at HTMLButtonElement.<anonymous> (platform-browser.js:988)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:3811)
改为此代码有效:
onShowAllOptions() {
const button1 = document.getElementById('button1');
const button2 = document.getElementById('button2');
const button3 = document.getElementById('button3');
const button4 = document.getElementById('button4');
const showallbutton = document.getElementById('showallbutton');
button1.classList.toggle('hide');
button2.classList.toggle('hide');
button3.classList.toggle('hide');
button4.classList.toggle('hide');
showallbutton.classList.add('hide');
}
我觉得我缺少一些基本的东西,我希望你能帮助我。谢谢!
解决方案
首先,我建议不要通过标准的浏览器方法来管理 DOM,比如document.getElementById
等。推荐使用 Angular 抽象,你可以在这里阅读更多内容。
顺便说一句,我们可以找到原因。
初始化时Skulder14q1Component
,它的 DOM(HTML 元素/模板)尚未创建。因此,当您尝试查找按钮时,它们还不存在,因此getElementById
返回null
。
Angular 中的组件经历了一个生命周期,你可以通过向你的类中添加某些方法来挂钩这个生命周期。您可以在有关生命周期钩子的文档中阅读有关这些内容的更多信息。
在你的情况下,你需要AfterViewInit
钩子。为了实现它,我们需要做两件事:
实现接口
AfterViewInit
class Skulder14q1Component implements AfterViewInit { ... }
添加方法
class Skulder14q1Component implements AfterViewInit { button1: HTMLElement; button2: HTMLElement; button3: HTMLElement; button4: HTMLElement; showAllButton: HTMLElement; ngAfterViewInit() { this.button1 = document.getElementById('button1'); this.button2 = document.getElementById('button2'); this.button3 = document.getElementById('button3'); this.button4 = document.getElementById('button4'); this.showallbutton = document.getElementById('showallbutton'); } // when this is called later, the buttons will have been set up onShowAllOptions() { this.button1.classList.toggle('hide'); this.button2.classList.toggle('hide'); this.button3.classList.toggle('hide'); this.button4.classList.toggle('hide'); this.showallbutton.classList.add('hide'); } }
该方法中的代码将在 Angular 为您准备好模板后运行。
编辑:根据我的经验,ViewChild
不经常使用,因为您希望模板中的元素(特别是如果它们是其他组件)对自己的行为负责,而不是控制全能类的所有内容。
这是我为您的用例制作的StackBlitz 。
推荐阅读
- angular - 有条件地在 Angular Http 拦截器中设置标题
- database - 对多个索引的 Elasticsearch 查询非常慢
- c# - 覆盖使用 Polly 定义的 HttpClientFactory 策略
- javascript - createObjectURL:使用 Blob 时在 Safari 中键入错误
- javascript - 如何在函数调用中从数组中一一返回值?
- python - Python matplotlib 的 FuncAnimation 无法通过内部 Latex 渲染和 PyCharm 正确关闭?
- javascript - 基于 if 语句获取
- c# - 在 MVVM 项目中找不到默认端点
- tensorflow - 为什么评估骰子损失与评估骰子度量不同?
- python - 如何找到自相关和偏自相关的滞后数?