在组件模板中,添加ng-content
标签,让你希望投影的内容出现在其中。ng-content
标签可以理解为插槽。
注意:
-
ng-content
标签必须是空标签,如该标签有内容,会报编译错误,而Vue
的slot
插槽不会(可对比学习)。 -
ng-content
标签是一个占位符,它不会创建真正的 DOM 元素。其自定义属性将被忽略。
单插槽内容投影
组件模板只含有一个<ng-content></ng-content>
标签
<!-- 子组件 app-son 的模板 -->
<div>
<header>头部</header>
<ng-content></ng-content>
<footer>底部</footer>
</div>
投影的内容可以是文本、一段HTML
、也可以是组件。投影的内容将出现在子组件ng-content
标签的位置。
<!-- 父组件 app-father 的模板 -->
<div>
<app-son>我是投影的文本内容</app-son> <!-- 投影内容是文本 -->
<app-son>
<h1>我是投影的h1标签</h1> <!-- 投影内容是HTML -->
</app-son>
<app-son>
<app-other></app-other> <!-- 投影内容是其他组件 -->
</app-son>
</div>
多插槽内容投影
组件模板含有多个<ng-content></ng-content>
标签。
为了区分投影的内容可以投影到对应ng-content
标签,需要使用ng-content
标签上的select
属性作为识别。
select
属性支持标签名、属性、CSS
类和 :not
伪类的任意组合。
不添加select
属性的ng-content
标签将作为默认插槽。所有为匹配的投影内容都会投影在该ng-content
的位置。
<!-- 子组件 app-son 的模板 -->
<div>
<header>头部</header>
<ng-content select="[property]"></ng-content>
<ng-content select="h3"></ng-content>
<ng-content select=".active"></ng-content>
<ng-content select="#hello"></ng-content>
<ng-content></ng-content> <!-- 默认插槽 -->
<footer>底部</footer>
</div>
投影内容会根据ng-content
标签上的select
属性投影在指定的位置。
<!-- 父组件 app-father 的模板 -->
<div>
<app-son>
<h3>h3标签</h3>
<div property>带property属性</div>
<div id="hello">id为hello</div>
<div class="active">class包含active类</div>
</app-son>
</div>
以上投影内容都是select
属性指定的直接子节点,如果用div
标签包裹h3
标签,让h3
标签不是select="h3"
指定的直接子节点。
<!-- 父组件 app-father 的模板 -->
<div>
<app-son>
<div>
<h3>h3标签</h3>
</div>
<div property>带property属性</div>
<div id="hello">id为hello</div>
<div class="active">class包含active类</div>
</app-son>
</div>
我们发现h3
标签的投影内容出现的位置发生了变化,出现在不带select
属性的ng-content
标签上,即默认插槽上。假如没有默认插槽,h3
标签的投影内容将不显示。
我们可以设置 ngProjectAs
属性的值与select
属性的值相匹配,来处理h3
标签投影内容的位置不正确的情况(即投影内容不是作为直接子节点,而是作为非直接子节点的情况)。
<!-- 父组件 app-father 的模板 -->
<div>
<app-son>
<div ngProjectAs="h3">
<h3>h3标签</h3>
</div>
<div property>带property属性</div>
<div id="hello">id为hello</div>
<div class="active">class包含active类</div>
</app-son>
</div>
设置 ngProjectAs
属性后,h3
标签投影内容的位置回复正常。