Angular4升级Angular8:Renderer的projectNodes作用及Renderer2替代方案
Hey there! Let me break this down for you as you're migrating from Angular 4 to 8 and swapping out the old Renderer for Renderer2.
Renderer.projectNodes and Migrating to Renderer2 What did Renderer.projectNodes actually do?
The projectNodes method in the legacy Renderer API was a convenience helper for bulk-adding an array of DOM nodes as children to a target parent node. Here's a clear breakdown of its behavior:
- It accepted two parameters: a target parent node (like
document.bodyin your code) and an array of nodes to attach. - Under the hood, it essentially ran
target.appendChild(node)for every item in the nodes array — appending each node to the end of the parent's child list. - Critical detail: If any of the nodes were already attached elsewhere in the DOM, they would be moved (not copied) to the target parent. DOM nodes can only exist in one place at a time, so this matches native DOM behavior.
Migration to Renderer2
Renderer2 doesn't include a direct replacement for projectNodes because its API aligns more closely with standard native DOM methods (which don't have a built-in bulk append for nodes). Instead, you can replicate the exact behavior using Renderer2.appendChild in a simple loop.
Step-by-Step Upgrade
- Replace the bulk method with iterative appends: Loop through your array of nodes and add each one to the target parent individually.
- (Optional, but recommended) Use Angular's
DOCUMENTinjection: Instead of directly referencingdocument.body, inject theDOCUMENTtoken for better testability and to follow Angular's dependency injection best practices.
Here's the upgraded code:
First, update your dependencies injection (if you haven't already):
import { Renderer2, Inject } from '@angular/core'; import { DOCUMENT } from '@angular/common'; // Inside your component/service constructor constructor( private _renderer: Renderer2, @Inject(DOCUMENT) private document: Document, // Keep your existing dependencies like _element, backdrop ) {}
Then replace your original projectNodes call with this:
const targetParent = this.document.body; const nodesToAdd = [ this._element.nativeElement, this.backdrop.instance.element.nativeElement ]; // Append each node to the target parent in order nodesToAdd.forEach(node => { this._renderer.appendChild(targetParent, node); });
Key Notes
- Order is preserved: Just like
projectNodes, nodes will be added to the parent in the exact order they appear in your array. - Node movement behavior stays the same: If a node was already in the DOM, it will be moved to the target parent (not duplicated), matching the original method's behavior.
- Minimize direct DOM access: If your target parent isn't
document.body, use Angular'sViewChildorElementRefto get a reference instead of querying the DOM directly — this keeps your code more Angular-friendly.
内容的提问来源于stack exchange,提问作者mathlearner

