【问题标题】:Is it OK to use getElementById in Angular?在 Angular 中使用 getElementById 可以吗?
【发布时间】: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')访问元素。
  • 这个答案会对你有所帮助,stackoverflow.com/questions/38944725/…
  • 以这种方式使用它的文档中的奇怪样本我猜它“没问题”,然后当样本在官方文档中时:D 我根本不会这样做。我可能会将表单控件附加到输入并收听valueChanges

标签: angular rxjs


【解决方案1】:

在 Angular 中使用手动处理 DOM 是一种糟糕的方法。在 Angular 应用程序中,您应该始终使用 Angular 的方法来呈现页面。因为在大多数情况下,您将来需要为您的应用程序提供服务器端渲染,以使其对 Google 友好。但是后端的 Angular 的 SSR 引擎(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的一个很好的例子

    【讨论】:

    【解决方案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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-22
      • 2017-06-26
      • 2019-02-21
      • 2015-08-23
      • 2016-06-29
      • 1970-01-01
      • 2013-05-25
      • 1970-01-01
      相关资源
      最近更新 更多