[Angular] 笔记 22:ElementRef

chatgpt:

ElementRef 是 Angular 中的一个类,它用于包装对 DOM 元素的引用。它允许开发者直接访问与 Angular 组件关联的宿主 DOM 元素。

当在 Angular 中需要直接操作 DOM 元素时,可以使用 ElementRef。通常情况下,最好避免直接操作 DOM,而是使用 Angular 的数据绑定和指令。但在一些特殊情况下,比如集成第三方库或需要直接操纵 DOM 的特定功能中,ElementRef 可能会派上用场。

需要注意的是,直接操作 DOM 可能会破坏 Angular 的变更检测机制,因此在使用 ElementRef 时应该小心谨慎,并确保操作的是被封装在 Angular 生命周期和变更检测机制内的特定元素。

以下是一个简单的示例,展示了在 Angular 中如何使用 ElementRef

ts 复制代码
import { Component, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<div #myDiv>Some content</div>',
})
export class ExampleComponent implements AfterViewInit {
  constructor(private elementRef: ElementRef) {}

  ngAfterViewInit() {
    // 使用 ElementRef 获取宿主 DOM 元素
    const divElement: HTMLElement = this.elementRef.nativeElement.querySelector('#myDiv');
    
    // 在这里可以直接操作 DOM 元素
    divElement.style.color = 'red';
  }
}

在这个示例中,ElementRef 被注入到了 ExampleComponent 的构造函数中,并在 ngAfterViewInit 生命周期钩子中使用它来获取 #myDiv 的宿主 DOM 元素,并修改了其文字颜色。

使用元素引用(ElementRef)有一些注意事项。

绕过 Angular 的抽象层: 直接操作 DOM 元素可能会绕过 Angular 的变更检测机制,导致应用程序中的一些问题。Angular 的核心优势之一是其数据绑定和变更检测能力,直接操作 DOM 可能会破坏这种优势。

安全风险: 操作原始的 DOM 元素可能存在安全风险。例如,直接操作 DOM 元素可能导致潜在的跨站脚本(XSS)攻击,因此需要谨慎处理用户输入的数据。

跨平台兼容性: 直接访问 DOM 可能会使应用程序的跨平台兼容性降低。Angular 的抽象层使得应用程序更容易在不同的平台和环境中运行,但直接操作 DOM 可能会导致在特定平台上出现问题。

维护困难: 直接的 DOM 操作可能会导致代码变得更难维护。随着应用程序的发展和变化,直接与 DOM 交互的部分可能需要更频繁的更新和维护。

总体来说,虽然 ElementRef 提供了直接访问 DOM 元素的能力,但是在使用它时需要谨慎考虑这些注意事项,尽量避免直接操作 DOM,而是优先使用 Angular 的抽象机制和指令来管理视图。


Angular For Beginners - 26. ElementRef

ElementRef 总是与 @ViewChild 一起使用。

使用 @ViewChild 获取数据。

使用 ElementRef 操纵这些获取的数据是最快速,最简单,同时也是最危险的方式。

1. 避免在组件上使用 @ViewChild

虽然可以,但如果在组件上使用 @ViewChild,就不会获得所有 javascript 属性。

pokemon-list.component.html: <th> 元素添加 #pokemonTh:

html 复制代码
<table>
  <thead>
    <th #pokemonTh>Name</th>
    <th>Index</th>
  </thead>
  <tbody>
    <app-pokemon-detail
      #pokemonRef
      *ngFor="let pokemon of pokemons"
      [detail]="pokemon"
      (remove)="handleRemove($event)"
    >
      <h1>-----------------------</h1>
      <h2>============================</h2>
      <h3></h3>
    </app-pokemon-detail>
  </tbody>
</table>

pokemon-list.component.ts:

ts 复制代码
import {
  AfterViewInit,
  Component,
  ElementRef,
  OnInit,
  ViewChild,
  ViewChildren,
} from '@angular/core';
import { Pokemon } from 'src/app/models/pokemon';
import { PokemonService } from 'src/app/services/pokemon.service';

@Component({
  selector: 'app-pokemon-list',
  templateUrl: './pokemon-list.component.html',
  styleUrls: ['./pokemon-list.component.css'],
})
export class PokemonListComponent implements OnInit, AfterViewInit {
  pokemons: Pokemon[] = [];

  @ViewChildren('pokemonRef') pokemonRef!: ElementRef;
  @ViewChild('pokemonTh') pokemonTh!: ElementRef;
  constructor(private pokemonService: PokemonService) {}

  // 新代码
  ngAfterViewInit(): void {
    console.log('ngAfterViewInit begin');
    console.log(this.pokemonTh);
    this.pokemonTh.nativeElement.innerText="Pokemon Name"
    console.log('ngAfterViewInit end');
  }

  handleRemove(event: Pokemon) {
    this.pokemons = this.pokemons.filter((pokemon: Pokemon) => {
      return pokemon.id !== event.id;
    });
  }

  ngOnInit(): void {
    // 填充 pokemons 属性
    // this.pokemons = this.pokemonService.getPokemons();
    this.pokemonService.getPokemons().subscribe((data: Pokemon[]) => {
      console.log(data);
      this.pokemons = data;
    });
  }
}

2. Web 页面

Name 变成了 Pokemon Name, console 里还可以看到除了 innerText 之外的其他属性.

相关推荐
天天爱吃肉821823 分钟前
第十篇:电源设计的“能量矩阵”——无线充电与碳化硅LLC谐振
笔记·矩阵·汽车
Smile_Gently2 小时前
前端:最简单封装nmp插件(组件)过程。
前端·javascript·vue.js·elementui·vue
luckycoke8 小时前
小程序立体轮播
前端·css·小程序
一 乐8 小时前
高校体育场管理系统系统|体育场管理系统小程序设计与实现(源码+数据库+文档)
前端·javascript·数据库·spring boot·高校体育馆系统
懒羊羊我小弟8 小时前
常用Webpack Loader汇总介绍
前端·webpack·node.js
祈澈菇凉9 小时前
ES6模块的异步加载是如何实现的?
前端·javascript·es6
我爱学习_zwj9 小时前
4.从零开始学会Vue--{{组件通信}}
前端·javascript·vue.js·笔记·前端框架
顾比魁9 小时前
XSS盲打:当攻击者“盲狙”管理员
前端·网络安全·xss
黑客老李9 小时前
新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
java·运维·服务器·前端·xss
好评笔记9 小时前
深度学习笔记——循环神经网络之LSTM
笔记·rnn·深度学习