Why I can't access template DOM element in the constructor of the component

与世无争的帅哥 提交于 2019-12-23 03:03:47

问题


Starting with RxJS and want to create a simple stream of button clicks, so I simply do this:

export class AppComponent {

    button : HTMLElement = document.querySelector('button');

    refreshClickStream$ = Observable.fromEvent(this.button, 'click')
       .subscribe();

    constructor(){
    }  

but receive that error in console...

Also tried it like this:

  clicked(e) {
    return Observable.fromEvent(e.target, 'click')
    .do(console.log)
       .subscribe();
  }

But after first click I get no output in console. After second click I get one MouseEvent object. After third click I get two MouseEvent Objects. After fourth click I get three of them etc. So I think click event handler duplicates with RxJS fromEvent function.

Any explanations are very welcome..


回答1:


You have the following setup:

AppComponent 
   template: '<button>some button</button>'
   button : HTMLElement = document.querySelector('button');

The top level code you put in the class will be used as a body of the constructor when transpiled to JavaScript:

class AppComponent {
   constructor() {
       let HTMLElement = document.querySelector('button');
   }
}

Now, Angular goes through the tree of components and creates a view with DOM nodes for each component one by one. So it first creates a view for the component that hosts app-component. It generates a DOM host element for it and then calls the AppComponent constructor. At this point the view for the AppComponent with button DOM element hasn't been created yet. So when the constructor is executed, you try to find the DOM element button which is not yet created.

To do you what you're trying to do you can use any of the lifecycle hooks. To get more information read my answer for the Difference between Constructor and ngOnInit.

Besides this problem, I would also advise to use @ViewChild for the DOM query and ngOnInit lifecycle hook like this:

template: `<button #b>...</button>`
...
class AppComponent {
   @ViewChild('b') button;

   ngOnInit() {
       this.refreshClickStream$ = Observable.fromEvent(this.button, 'click').subscribe();
   }
}


来源:https://stackoverflow.com/questions/45464973/why-i-cant-access-template-dom-element-in-the-constructor-of-the-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!