如何在Angular 2中获取`DOM元素`?
如何在Angular 2中获取`DOM元素`?
这个问题已经有答案了:
我有一个包含
元素的组件。其中的 (click)
事件将把它改变成
<ul>
<li>我如何让焦点在 <code>textarea</code> 上?</li>
<li>我如何获取该元素,以便能够对其应用 <code>.focus()</code> ?</li>
<li>我能否避免使用 <code>document.getElemenntById()</code>?</li>
</ul>
<p>我尝试使用 \"ElementRef\" 和 \"@ViewChild()\",但似乎缺少了一些内容:</p>
<p><strong>app.component.ts</strong></p>
<p></p> <pre>@ViewChild('tasknoteId') taskNoteRef:ElementRef; noteEditMode: boolean = false; get isShowNote (){ return !this.noteEditMode && this.todo.note ? true : false; } taskNote: string; toggleNoteEditMode () { this.noteEditMode = !this.noteEditMode; this.renderer.invokeElementMethod( this.taskNoteRef.nativeElement,'focus' ); } </pre> <p></p>
<p><strong>app.component.html</strong></p>
<p></p> <pre><span class="the-insert"> </p> <form [hidden]="!noteEditMode && todo.note"> <textarea #tasknoteId id="tasknote" name="tasknote" [(ngModel)]="todo.note" placeholder="{{ notePlaceholder }}" style="background-color:pink" (blur)="updateNote()" (click)="toggleNoteEditMode()" [autofocus]="noteEditMode" [innerHTML]="todo.note">
更新(使用渲染器):
请注意,原始的Renderer服务现已被Renderer2替代。
有关详细信息,请参阅Renderer2官方文档。
此外,正如@GünterZöchbauer指出的那样:
实际上,使用ElementRef非常好。还可以使用Renderer2的ElementRef.nativeElement。不鼓励直接访问ElementRef.nativeElement.xxx的属性。
您可以通过使用elementRef
和ViewChild
来实现此操作。但是,由于存在以下原因,不建议使用elementRef
:
- 安全问题
- 紧密耦合
正如官方ng2文档所指出的那样。
1.使用elementRef
(直接访问):
export class MyComponent { constructor (private _elementRef : ElementRef) { this._elementRef.nativeElement.querySelector('textarea').focus(); } }
2.使用ViewChild
(更好的方法):
// <-- changes id to local var export class MyComponent implements AfterViewInit { @ViewChild('tasknote') input: ElementRef; ngAfterViewInit() { this.input.nativeElement.focus(); } }
3.使用renderer
:
export class MyComponent implements AfterViewInit { @ViewChild('tasknote') input: ElementRef; constructor(private renderer: Renderer2){ } ngAfterViewInit() { //using selectRootElement instead of depreaced invokeElementMethod this.renderer.selectRootElement(this.input["nativeElement"]).focus(); } }
使用ViewChild和#TemplateVariable如下所示:
在组件中,
最老的方式
import {ElementRef} from '@angular/core'; @ViewChild('someVar') el:ElementRef; ngAfterViewInit() { this.el.nativeElement.focus(); }
老方式
import {ElementRef} from '@angular/core'; @ViewChild('someVar') el:ElementRef; constructor(private rd: Renderer) {} ngAfterViewInit() { this.rd.invokeElementMethod(this.el.nativeElement,'focus'); }
更新于 2017 年 03 月 22 日
新方式
请注意,从Angular v4.0.0-rc.3(2017-03-10)开始,有些事情已经改变。
由于Angular团队将弃用invokeElementMethod
,上述代码不能再使用。
重大变更
自 4.0 rc.1 开始:
将 RendererV2 重命名为 Renderer2
将 RendererTypeV2 重命名为 RendererType2
将 RendererFactoryV2 重命名为 RendererFactory2
import {ElementRef,Renderer2} from '@angular/core'; @ViewChild('someVar') el:ElementRef; constructor(private rd: Renderer2) {} ngAfterViewInit() { console.log(this.rd); this.el.nativeElement.focus(); //<<<=====same as oldest way }
console.log(this.rd)
将给出以下方法,您现在可以看到invokeElementMethod
不在其中。附加img,因为它尚未记录。
注意: 您可以使用Rendere2
的以下方法来做很多事情,带/不带ViewChild变量。