使用ng-content进行组件内容投射
原文
https://www.jianshu.com/p/c0a39b1776c0
大纲
1、认识内容投射
2、一个简单组件
3、简单投射
4、针对性投射
5、ngProjectAs
6、代码资源
认识内容投射
在angular中,组件属于特殊的指令,它的特殊之处在于它有自己的模板(html)和样式(css)。因此使用组件可以使我们的代码具有强解耦、可复用、易扩展等特性。
一个简单组件
/* demo.component.ts */ import { Component, OnInit } from ‘@angular/core‘; @Component({ selector: 'demo-component', templateUrl: './demo.component.html', styleUrls: ['./demo.component.scss'] }) export class DemoComponent implements OnInit { constructor() { } ngOnInit() { } }
<!-- demo.component.html: --> <div class="demo"> <h2> demo-component - 我是一个简单的组件 </h2> </div>
/* demo.component.scss: */ .demo { padding: 10px; border: 2px solid red; h2 { margin: 0; color: #262626; } }
<!-- 此时我们引用该组件,就会呈现该组件解析之后的内容: --> <demo-component></demo-component>
需求
假设现在有这样的需求,这个组件能够接受外部投射进来的内容,也就是说组件最终呈现的内容不仅仅是本身定义的那些,那该怎么做呢?这时就要请出本文的主角 ng-content。
简单投射
<!-- demo.component.html: --> <div class="demo"> <h2> demo-component - 可嵌入外部内容的组件 </h2> <div class="content"> <ng-content></ng-content> </div> </div>
/* demo.component.scss: */ .demo { padding: 10px; border: 2px solid red; h2 { margin: 0; color: #262626; } .content { padding: 10px; margin-top: 10px; line-height: 20px; color: #FFFFFF; background-color: #de7d28; } }
<!-- 为了效果展示特意将 所在的容器背景色定义为橙色。 这时我们在引用该组件时可以从外部投射内容,外部内容将在橙色区域显示: --> <demo-component> 我是外部嵌入的内容 </demo-component>
针对性投射
如果同时存在几个外部内容,那外部内容将如何进行投射呢?如果同时存在简单的外部内容,那么外部内容将投射在组件模板最后的那个ng-content中。
<!-- demo.component.html: --> <div class="demo"> <h2> demo-component - 可嵌入外部内容的组件 </h2> <div class="content"> <ng-content></ng-content> </div> <div class="content blue"> <ng-content select="header"></ng-content> </div> <div class="content red"> <ng-content select=".demo2"></ng-content> </div> <div class="content green"> <ng-content select="[name=demo3]"></ng-content> </div> </div>
/* demo.component.scss: */ .demo { padding: 10px; border: 2px solid red; h2 { margin: 0; color: #262626; } .content { padding: 10px; margin-top: 10px; line-height: 20px; color: #FFFFFF; background-color: #de7d28; &.blue { background-color: blue; } &.red { background-color: red; } &.green { background-color: green; } } }
<!-- 从上面代码可以看到,蓝色区域将接收 标签 header 那部分内容, 红色区域将接收 class为"demo2"的div 的那部分内容, 绿色区域将接收 属性name为"demo3"的div 的那部分内容, 橙色区域将接收其余的外部内容(开始,我是外部嵌入的内容,结束)。 引用该组件:此时,我们将看到外部内容投射到了指定的 中。 --> <demo-component> 开始,我是外部嵌入的内容, <header> 我是外部嵌入的内容,我在header中 </header> <div class="demo2"> 我是外部嵌入的内容,我所在div的class为"demo2" </div> <div name="demo3"> 我是外部嵌入的内容demo,我所在div的属性name为"demo3" </div> 结束 </demo-component>
ngProjectAs
现在我们知道通过 ng-content 的 select 属性可以指定外部内容投射到指定的元素中。
而要能正确的根据 select 属性投射内容,有个限制就是 - 不管是 标签 header、class为"demo2"的div还是 属性name为"demo3"的div,这几个标签都是作为 组件标签 的直接子节点。
通过设置 ngProjectAs 属性,让 标签header 所在的 div 指向了 select="header",此时 标签 header 那部分内容有投射到蓝色区域了。
<demo-component> 开始,我是外部嵌入的内容, <div ngProjectAs="header"> <header> 我是外部嵌入的内容,我在header中 </header> </div> <div class="demo2"> 我是外部嵌入的内容,我所在div的class为"demo2" </div> <div name="demo3"> 我是外部嵌入的内容demo,我所在div的属性name为"demo3" </div> 结束 </demo-component>
代码资源
angular实例代码中angular-ng-content中包含着使用ng-content进行组件内容投射,里面有本篇博客中所包含的所有实例,从一个简单组件到内容投射都含有,如果有兴趣的读者可以从git上下载下来尝试。