[Angular] 笔记 23:Renderer2 - ElementRef 的生产版本

chatgpt:

Renderer2 简介

在 Angular 中,Renderer2 是一个服务,用于处理 DOM 操作的抽象层。它提供了一种安全的方式来操作 DOM,同时与平台无关,有助于维护应用程序的跨浏览器兼容性和安全性。

Renderer2 的作用是在 Angular 组件中执行 DOM 操作,例如创建元素、设置属性、添加监听器、修改样式等。通过使用 Renderer2,开发者可以避免直接操作原始的 DOM 元素,而是通过 Angular 提供的抽象层来处理这些操作。

使用 Renderer2 的好处包括:

平台无关性 : Renderer2 提供了与平台无关的 DOM 操作,这意味着你的应用程序可以在不同的平台上运行,并且不需要针对特定浏览器或环境进行修改。

安全性 : 通过 Renderer2 执行 DOM 操作可以提高应用程序的安全性,因为它会遵循 Angular 的安全策略,并减少潜在的安全风险,比如 XSS 攻击。

可测试性 : 使用 Renderer2 可以更轻松地编写单元测试,因为你可以模拟和验证 DOM 操作,而无需实际操作 DOM。

使用 Renderer2 的例子可能如下所示:

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

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

  ngOnInit() {
    const divElement = this.el.nativeElement.querySelector('#myDiv');
    
    // 使用 Renderer2 设置元素的样式
    this.renderer.setStyle(divElement, 'color', 'red');
  }
}

在这个例子中,Renderer2 被注入到了 ExampleComponent 的构造函数中,并用于设置 #myDiv 元素的文字颜色。这样,通过 Renderer2 来操作 DOM,而不是直接操作原始的 DOM 元素,提供了更好的安全性和跨平台兼容性。

为什么不叫 Renderer 而是叫 Renderer2 呢?

在 Angular 中,Renderer2 取代了早期版本中的 Renderer 接口。原先的 Renderer 接口存在一些限制和性能问题,并且与新的 Web 标准和浏览器 API 不够契合。

当 Angular 团队重新设计和改进渲染器接口时,他们引入了 Renderer2Renderer2 提供了更好的抽象,更好地与现代浏览器 API 对接,同时也改善了性能和安全性。为了明确表示这是一个新的、改进过的版本,他们将其命名为 Renderer2,以示区别。

虽然 Renderer2 在命名上带有 "2",但它并不是简单的旧版本的更新。它是从头重新设计的、更先进、更灵活和更与时俱进的渲染器接口。这也是为什么现在推荐使用 Renderer2 而不是旧的 Renderer 接口。


Angular For Beginners - 27. Renderer2

Renderer2ElementRef 的 production version, ElementRef 由于缺乏安全性,只适应于小型的个人项目。

1. 用法:

ts 复制代码
import {
  AfterViewInit,
  Component,
  ElementRef,
  OnInit,
  Renderer2,
  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,
    private renderer: Renderer2  // 引入 renderer2 !!!
  ) {}

  // 使用 renderer2
  ngAfterViewInit(): void {
    console.log(this.pokemonTh);
    this.pokemonTh.nativeElement.innerText = 'Pokemon Name';
    const div=this.renderer.createElement('div');
    const text = this.renderer.createText('Pokemon List')
    this.renderer.appendChild(div, text);
    this.renderer.appendChild(this.pokemonTh.nativeElement, div)
  }

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

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

2. web 页面:

相关推荐
索西引擎2 分钟前
【React】useState 状态更新机制:批量更新策略与“异步“错觉的深层解析
前端·react.js·前端框架
慢功夫19 分钟前
💡第五篇:VSCode插件是如何与主进程通信的?
前端·visual studio code
锋行天下22 分钟前
打造企业内部知识库系统RAG全栈项目
前端·后端·架构
竹林81833 分钟前
用 ethers.js 连接 MetaMask 实现钱包登录:一个真实项目中的完整踩坑记录
前端·javascript
zhangrelay37 分钟前
笔记本轻量高品质延寿工具完整分系统清单
运维·笔记·学习
巴巴媛66643 分钟前
STM32学习笔记【38.DHT11实验】
笔记·stm32·学习
虚惊一场1 小时前
在浏览器里跑 Prettier:格式化 Markdown 的四个难点
前端·javascript·vue.js
前端炒粉1 小时前
手撕小汇总
java·前端·javascript
r_oo_ki_e_1 小时前
vue快速入门
前端·vue.js
虚惊一场1 小时前
把 CodeMirror 6 调教成 Markdown 编辑器:扩展、装饰与门面
前端·javascript·vue.js