了解Angular范围

时间:2018-10-19 16:01:58

标签: angular

我对棱角还很陌生,所以我希望这个问题不太基本。我正在尝试在angular中运行一个函数,但是我的变量范围似乎有问题。看起来像这样:

echo '<img src="cinematheque-app/'.$row['image_url'].'" class="img-thumbnail">';

现在通过按一个按钮即可运行该功能,但是当按下该按钮时,控制台日志将返回以下内容:

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)

我觉得我缺少一些基本知识,希望您能帮助我。谢谢!

1 个答案:

答案 0 :(得分:1)

首先,我建议不要通过诸如document.getElementById等标准浏览器方法来过多地管理DOM。建议使用Angular抽象,您可以阅读更多here

这很简单,我们可以了解为什么

初始化Skulder14q1Component时,尚未为其创建DOM(HTML元素/模板)。因此,当您尝试查找按钮时,它们还不存在,因此getElementById返回null

Angular中的组件会经历一个生命周期,您可以通过向类中添加某些方法来陷入这个生命周期。您可以在docs on lifecycle hooks中详细了解这些内容。

在您的情况下,您需要使用AfterViewInit钩子。要实现它,我们需要做两件事:

  1. 实现接口AfterViewInit

    class Skulder14q1Component implements AfterViewInit {
    ...
    }
    
  2. 添加方法

    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