1. 程式人生 > 其它 >Angular 內容投影出現 No provider for TemplateRef found 錯誤的單步除錯

Angular 內容投影出現 No provider for TemplateRef found 錯誤的單步除錯

問題描述

本文涉及到的程式碼位置:https://github.com/wangzixi-diablo/ngDynamic

我有一個能接受內容投影的 Angular Component:

使用如下程式碼消費這個 Component:

但是遇到執行時錯誤,如下圖所示。
點選 template.html:7:3:


問題分析

丟擲該錯誤訊息的函式實現:

/**
 * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.
 *
 * Look for the injector providing the token by walking up the node injector tree and then
 * the module injector tree.
 *
 * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom
 * filter. Negative values are reserved for special objects.
 *   - `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)
 *
 * @param tNode The Node where the search for the injector should start
 * @param lView The `LView` that contains the `tNode`
 * @param token The token to look for
 * @param flags Injection flags
 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided
 */
function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default, notFoundValue)

第一個輸入引數 tnode 就是 p 節點本身:

token 指向 TemplateRef

解決方案

這個問題有幾種解決方案。

方案1

刪除 p 節點的自定義 Directive:

然後新增一個預設的內容投影:

解決方案2

刪除自定義 Directive 建構函式裡的 TemplateRef 依賴:

解決方案3

消費 zippy Component 時,直接傳入被投影的內容:

該內容會被投影到下圖第一行的 place holder:

解決方案4

消費 Component 時,通過 ng-template + 自定義 Directive 的方式指定被投影的內容:

通過 @ContentChild

conten query 拿到自定義 Directive 例項,進而拿到 Directive 指向的 TemplateRef

總結

渲染樹是實際的 DOM 渲染樹。 它與 Ivy 的邏輯樹不同,渲染樹必須考慮內容投影。 因此渲染樹裡的父/子關係不像邏輯檢視中那樣簡單。