angular-docs-cn/aio/content/guide/migration-renderer.md
Zhicheng WANG 8675bc5719 docs: 合并远端更新
初步合并了冲突,尚未校验,四个改动很大的章节暂时改回了英文版
2020-06-12 18:18:15 +08:00

7.9 KiB
Raw Blame History

Renderer to Renderer2 migration

RendererRenderer2 的迁移

Migration Overview

迁移概述

The Renderer class has been marked as deprecated since Angular version 4. This section provides guidance on migrating from this deprecated API to the newer Renderer2 API and what it means for your app.

自 Angular 版本 4 开始,Renderer 类就被标记为已弃用。本节提供了一些指导,帮助你把这个已弃用的 API 迁移到更新的 Renderer2 API并解释了它对你的应用而言意味着什么。

Why should I migrate to Renderer2?

为什么要迁移到 Renderer2

The deprecated Renderer class has been removed in version 9 of Angular, so it's necessary to migrate to a supported API. Using Renderer2 is the recommended strategy because it supports a similar set of functionality to Renderer. The API surface is quite large (with 19 methods), but the schematic should simplify this process for your applications.

已弃用的 Renderer 类已经在 Angular 的 9 中删除了,所以有必要迁移到支持的 API。建议使用 Renderer2 策略,因为它支持与 Renderer 很相似的一组功能。这个 API 非常庞大(有 19 种方法),但原理图会帮你简化这个过程。

Is there action required on my end?

完成后我还要采取什么行动吗?

No. The schematic should handle most cases with the exception of Renderer.animate() and Renderer.setDebugInfo(), which already aren't supported.

这个原理图应该可以处理大多数情况,仅仅不支持 Renderer.animate()Renderer.setDebugInfo()

What are the __ngRendererX methods? Why are they necessary?

什么是 __ngRendererX 方法族?为什么要用它们?

Some methods either don't have exact equivalents in Renderer2, or they correspond to more than one expression. For example, both renderers have a createElement() method, but they're not equal because a call such as renderer.createElement(parentNode, namespaceAndName) in the Renderer corresponds to the following block of code in Renderer2:

有些方法在 Renderer2 没有完全等价的东西,或者对应于多个表达式。例如,这两种渲染器都有 createElement() 的方法,但它们是不相等的,比如在 Renderer 中调用 renderer.createElement(parentNode, namespaceAndName) 时对应 Renderer2 中的如下代码块

const [namespace, name] = splitNamespace(namespaceAndName);
const el = renderer.createElement(name, namespace);
if (parentNode) {
  renderer.appendChild(parentNode, el);
}
return el;

Migration has to guarantee that the return values of functions and types of variables stay the same. To handle the majority of cases safely, the schematic declares helper functions at the bottom of the user's file. These helpers encapsulate your own logic and keep the replacements inside your code down to a single function call. Here's an example of how the createElement() migration looks:

迁移必须保证函数和变量类型的返回值不变。此原理图会安全地处理大多数情况,它会在用户文件的底部声明一些辅助函数。这些辅助函数封装了你自己的逻辑,把代码中要被替换的内容放到单个函数调用中。这里是 createElement() 迁移工作原理的一个例子:

Before:

之前:

public createAndAppendElement() {
  const el = this.renderer.createElement('span');
  el.textContent = 'hello world';
  return el;
}

After:

之后:

public createAndAppendElement() { const el = __ngRendererCreateElement(this.renderer, this.element, 'span'); el.textContent = 'hello world'; return el; } // Generated code at the bottom of the file __ngRendererCreateElement(renderer: any, parentNode: any, nameAndNamespace: any) { const [namespace, name] = __ngRendererSplitNamespace(namespaceAndName); const el = renderer.createElement(name, namespace); if (parentNode) { renderer.appendChild(parentNode, el); } return el; } __ngRendererSplitNamespace(nameAndNamespace: any) { // returns the split name and namespace }

When implementing these helper functions, the schematic ensures that they're only declared once per file and that their names are unique enough that there's a small chance of colliding with pre-existing functions in your code. The schematic also keeps their parameter types as any so that it doesn't have to insert extra logic that ensures that their values have the correct type.

当实现了这些辅助函数时,此原理图会确保它们在每个文件中都只声明一次,并且它们的名字是唯一的,因此和你的代码中已经存在的函数几乎不可能冲突。该原理图还会把它们的参数类型设为 any 使其不必插入额外的逻辑就能确保它们的值有正确的类型。

Im a library author. Should I run this migration?

我是库作者。我应该运行这次迁移吗?

Library authors should definitely use this migration to move away from the Renderer. Otherwise, the libraries won't work with applications built with version 9.

库的作者肯定要做这种迁移来远离 Renderer。否则,这些库将不再适用于用 Angular 9 构建的应用。

Full list of method migrations

方法迁移的完整列表

The following table shows all methods that the migration maps from Renderer to Renderer2.

下表列出了从 RendererRenderer2 要迁移的所有方法。

Renderer Renderer2
listen(renderElement, name, callback) listen(renderElement, name, callback)
setElementProperty(renderElement, propertyName, propertyValue) setProperty(renderElement, propertyName, propertyValue)
setText(renderNode, text) setValue(renderNode, text)
listenGlobal(target, name, callback) listen(target, name, callback)
selectRootElement(selectorOrNode, debugInfo?) selectRootElement(selectorOrNode)
createElement(parentElement, name, debugInfo?) appendChild(parentElement, createElement(name))
setElementStyle(el, style, value?) value == null ? removeStyle(el, style) : setStyle(el, style, value)
setElementAttribute(el, name, value?) attributeValue == null ? removeAttribute(el, name) : setAttribute(el, name, value)
createText(parentElement, value, debugInfo?) appendChild(parentElement, createText(value))
createTemplateAnchor(parentElement) appendChild(parentElement, createComment(''))
setElementClass(renderElement, className, isAdd) isAdd ? addClass(renderElement, className) : removeClass(renderElement, className)
projectNodes(parentElement, nodes) for (let i = 0; i < nodes.length; i++) { appendChild(parentElement, nodes[i]); }
attachViewAfter(node, viewRootNodes) const parentElement = parentNode(node); const nextSibling = nextSibling(node); for (let i = 0; i < viewRootNodes.length; i++) { insertBefore(parentElement, viewRootNodes[i], nextSibling);}
detachView(viewRootNodes) for (let i = 0; i < viewRootNodes.length; i++) {const node = viewRootNodes[i]; const parentElement = parentNode(node); removeChild(parentElement, node);}
destroyView(hostElement, viewAllNodes) for (let i = 0; i < viewAllNodes.length; i++) { destroyNode(viewAllNodes[i]); }
setBindingDebugInfo() This function is a noop in Renderer2.
setBindingDebugInfo() 该函数在 Renderer2 中无用。
createViewRoot(hostElement) Should be replaced with a reference to hostElement
createViewRoot(hostElement) 应该替换成到 hostElement 的引用
invokeElementMethod(renderElement, methodName, args?) (renderElement as any)[methodName].apply(renderElement, args);
animate(element, startingStyles, keyframes, duration, delay, easing, previousPlayers?) Throws an error (same behavior as Renderer.animate())
animate(element, startingStyles, keyframes, duration, delay, easing, previousPlayers?) 抛出一个错误 (和 Renderer.animate() 一样)