浅谈angular4 ng-content 中隐藏的内容
如果你尝试在Angular中编写可重复使用的组件,则可能会接触到内容投射的概念。然后你发现了,并找到了一些关于它的文章,进而实现了所需的功能。
接下来我们来通过一个简单的示例,一步步介绍所涉及的内容。
Simpleexample
在本文中我们使用一个示例,来演示不同的方式实现内容投影。由于许多问题与Angular中的组件生命周期相关,因此我们的主要组件将显示一个计数器,用于展示它已被实例化的次数:
import{Component}from'@angular/core';
letinstances=0;
@Component({
selector:'counter',
template:'{{this.id}}
'
})
classCounter{
id:number;
constructor(){
this.id=++instances;
}
}
上面示例中我们定义了Counter组件,组件类中的id属性用于显示本组件被实例化的次数。接着我们继续定义一个Wrapper组件:
import{Component}from'@angular/core';
@Component({
selector:'wrapper',
template:`
`
})
classWrapper{}
现在我们来验证一下效果:
Targetedprojection
有时你希望将包装器的不同子项投影到模板的不同部分。为了处理这个问题,支持一个select属性,可以让你在特定的地方投射具体的内容。该属性支持CSS选择器(my-element,.my-class,[my-attribute],...)来匹配你想要的内容。如果ng-content上没有设置select属性,它将接收全部内容,或接收不匹配任何其他ng-content元素的内容。长话短说:
import{Component}from'@angular/core';
@Component({
selector:'wrapper',
template:`
`,
styles:[`
.red{background:red;}
.blue{background:blue;}
`]
})
exportclassWrapper{}
上面示例中,我们引入了select属性,来选择投射的内容:
Thisisnotacounter
上述代码成功运行后,counter组件被正确投影到第二个蓝色框中,而span元素最终会在全部红色框中。请注意,目标ng-content会优先于catch-all,即使它在模板中的位置靠后。
ngProjectAs
有时你的内部组件会被隐藏在另一个更大的组件中。有时你只需要将其包装在额外的容器中即可应用ngIf或ngSwitch。无论什么原因,通常情况下,你的内部组件不是包装器的直接子节点。为了演示上述情况,我们将Counter组件包装在一个中,看看我们的目标投影会发生什么:
现在我们的couter组件会被投影到第一个红色框中。因为ng-container容器不再匹配select="counter"。为了解决这个问题,我们必须使用ngProjectAs属性,它可以应用于任何元素上。具体如下:
通过设置ngProjectAs属性,终于让我们的counter组件重回蓝色框的怀抱了。
Timetopokeandprod
我们从一个简单的实验开始:将两个块放在我们的模板中,没有选择器。会出现什么情况?
页面中会显示一个或两个框,如果我们包含两个框,它们的内容是显示1和1或1和2?