在 Angular 中使用 getElementById 可以吗?

Posted

技术标签:

【中文标题】在 Angular 中使用 getElementById 可以吗?【英文标题】:Is it OK to use getElementById in Angular? 【发布时间】:2020-01-23 05:22:19 【问题描述】:

我正在浏览 Angular 文档并看到以下代码 sn-p。在我的脑海里,我想我记得在 Angular 中使用 document.getElementById() 是不受欢迎的,甚至不鼓励使用 ElementRefs (以帮助防止 XSS 攻击)。如果确实不鼓励这些,那么为特定元素上的事件设置 Observable 的最佳实践是什么?

来自Angular Observables Documentation

import  fromEvent  from 'rxjs';
import  ajax  from 'rxjs/ajax';
import  map, filter, debounceTime, distinctUntilChanged, switchMap  from 'rxjs/operators';

const searchBox = document.getElementById('search-box');  // <-- Is this OK?

const typeahead = fromEvent(searchBox, 'input').pipe(
  map((e: KeyboardEvent) => e.target.value),
  filter(text => text.length > 2),
  debounceTime(10),
  distinctUntilChanged(),
  switchMap(() => ajax('/api/endpoint'))
);

【问题讨论】:

可以使用模板变量,然后使用@ViewChild('your template variable name')访问元素。 这个答案会对你有所帮助,***.com/questions/38944725/… 以这种方式使用它的文档中的奇怪样本我猜它“没问题”,然后当样本在官方文档中时:D 我根本不会这样做。我可能会将表单控件附加到输入并收听valueChanges 【参考方案1】:

在 Angular 中使用手动处理 DOM 是一种糟糕的方法。在 Angular 应用程序中,您应该始终使用 Angular 的方法来呈现页面。因为在大多数情况下,您将来需要为您的应用程序提供服务器端渲染,以使其对 Google 友好。但是后端的 Angular 的 s-s-r 引擎(Angular Universal)只模拟 XHR 对象,而不模拟 DOM 方法。

【讨论】:

【参考方案2】:

我建议使用 angulars ViewChild 与模板中的组件进行交互。

ViewChild - 装饰器 API

配置视图查询的属性装饰器。变化检测器 查找第一个元素或与选择器匹配的指令 视图 DOM。如果视图 DOM 发生变化,并且新的子节点匹配 选择器,属性已更新。

例如:

import Component, Directive, Input, ViewChild from '@angular/core';

@Directive(selector: 'pane')
export class Pane 
  @Input() id !: string;


@Component(
  selector: 'example-app',
  template: `
    <pane id="1" *ngIf="shouldShow"></pane>
    <pane id="2" *ngIf="!shouldShow"></pane>

    <button (click)="toggle()">Toggle</button>

    <div>Selected: selectedPane</div>
  `,
)
export class ViewChildComp 
  @ViewChild(Pane, static: false)
  set pane(v: Pane) 
    setTimeout(() =>  this.selectedPane = v.id; , 0);
  
  selectedPane: string = '';
  shouldShow = true;
  toggle()  this.shouldShow = !this.shouldShow; 

这是Understanding ViewChildren, ContentChildren, and QueryList in Angular的一个很好的例子

【讨论】:

我错了还是不再支持!: 语法? 嗯示例来自apiangular.io/api/core/ViewChild,可能已经过时了?【参考方案3】:

使用响应式可能是更好的方法

//html:
<input #search [formControl]="search"/>

//Component
search=new FormControl('')
search.valueChanges.pipe(
  filter(text => text.length > 2),
  debounceTime(10),
  distinctUntilChanged(),
  switchMap(() => ajax('/api/endpoint'))
).subscribe();

【讨论】:

以上是关于在 Angular 中使用 getElementById 可以吗?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 基础,登录验证

JavaScript 基础,登录前端验证

JavaScript 基础,登录前端验证

JavaScript 基础,登录前端验证

JavaScript 基础,登录前端验证

JavaScript 基础,登录前端验证