今天看到文章:https://segmentfault.com/a/1190000015944548 。专门研究一下ngTemplateOutlet用法!!!!
在我遇到的情况中,有两种时候会用到ngTemplateOutlet。
1、需要要自定义标题或页脚的内容。 比如弹窗组件不能在自己的内容中写死标题和页面的内容, 在页面上使用该组件时, 页面 动态向指定组件内占位传入“一些内容”,组件会把它们插入到它想要的地方! 比如ng-zorro中,大量这样用法,https://ng.ant.design/components/card/zh#components-card-demo-simple
2、递归组件使用时,要用到ngTemplateOutlet 来切换节点上的组件。 比如要定义菜单组件,涉及到两类组件,1是叶子菜单项,2是文件夹菜单项。
下图是看zorro的ISSUE中的一个截图, 其写法我不知道对不对。 递归组件的标准实践待确认!!!
下面我就这两个情况,实践讨论一下!
比如在一个页面上,引用nz-card时,把页面上<ng-template>内容插入到nz-card中去,
需要考虑几个问题,
1、如何引用当前面页上的一个元素( 本地变量 # ,我记得以前官方文档叫“局部模版变量"或“模板引用变量”) 2、引用的变量如何传递给子组件中(子组件用@Input 一个类型为TemplateRef<T>的变量接收) 3、子组件如何使用这个引用变量( 在模版中,用ngTemplateOutlet 绑定这个变量即可) 4、引用元素从主页面上来, 如何把子组件的数据(即子组件中上下文)传递给这个引用元素上来?(向ngTemplateOutlet 传入 context: myContext”)
上下文传递很重要。组件为了灵活,一部分内容定义在组件之外的(即主页面上),当它插入到子组件中的时候,必然要显示子组件内的一些数据,它才有意义。 ngTemplateOutlet 不仅用于绑定元素,还负责把子组件中的一个数据上下文传递进去.
5、模板元素如何使用上下文? (使用 模板输入变量let phone
的形式,接收内容,再用 {{ }}语法插入值)
定义上下文数据时, myContext = { $implicit: 'World', valueInContent: "子组件内的value" }; $implicit:是默认导出值。当let-name 后没= 号时,引用它。 参考官方文档:
完整而精巧的小例子:
import { Component, OnDestroy, OnInit, TemplateRef, Input } from '@angular/core';
/// 主页面
@Component({
selector: 'app-root',
template: `
<h1>Angular's ngTemplateOutlet 完整示意-----我是主页</h1>
<app-content [dynamicRef]="usedByContent"></app-content>
<ng-template #usedByContent let-name let-valueInContent=valueInContent>
<div style="margin-left:20px;border:dashed;">
<div>Hello {{name}}! 组件内的上下文绑定: {{valueInContent}} ....</div>
<div> 主页面的变量绑定: {{valueInApp}}</div>
</div>
</ng-template>`,
})
export class AppComponent {
public valueInApp = "valueInApp :)";
}
/// 一个子组件
@Component({
selector: 'app-content',
template: `
<div>我是子组件,下面的内容是动态加载 :)</div>
<template
*ngTemplateOutlet="dynamicRef context: myContext">
</template>
`,
})
export class AppContent {
display = false;
@Input() dynamicRef: TemplateRef<HTMLDivElement>;
myContext = { $implicit: 'World', valueInContent: "子组件内的value" };
}