本篇文章带大家聊聊angular中的内容投影,介绍一下使用ng-content进行内容投影的方法,并了解有条件内容投影的实现方法,希望对大家有所帮助!
一、 ng-content 进行内容投影1.1 ng-content
ng-content 元素是一个用来插入外部或者动态内容的占位符。父组件将外部内容传递给子组件,当 angular 解析模板时,就会在子组件模板中 ng-content 出现的地方插入外部内容。【相关教程推荐:《angular教程》】
我们可以使用内容投影来创建可重用的组件。这些组件有相似的逻辑和布局,并且可以在许多地方使用。一般我们在封装一些公共组件的时候经常会用到。
1.2 为什么使用内容投影
定义一个 button 组件:
button-component.ts
@component({ selector: '[appbutton]', template: ` <span class="icon-search"></span>`})export class appbuttoncomponent {}
这个 button 组件的目的是在按钮内部加一个搜索的图标,我们实际使用如下:
<button appbutton>click</button>
我们发现组件只会展示搜索图标, 按钮的文本不会展示,能你会想到最常使用的 @input 装饰器,但是如果我们不只是想传文本进来,而是传一段 html 进来呢?此时就会用到 ng-content。
1.3 单插槽内容投影
内容投影的最基本形式是单插槽内容投影。
单插槽内容投影是指创建一个组件,我们可以在其中投影一个组件。
以 button 组件为例,创建一个单槽内容投影:
button-component.ts
@component({ selector: '[appbutton]', template: ` <span class="icon-search"></span> <ng-content></ng-content>`})export class appbuttoncomponent {}
实际使用如下:
<button appbutton>click</button>
可以发现,现在这个 button 组件的效果是即显示了搜索图标,又显示了按钮的文本(click)。即把 <button appbutton></button> 中间的内容 投影 到了组件的 <ng-content></ng-content> 位置。
ng-content 元素是一个占位符,它不会创建真正的 dom 元素。ng-content 的那些自定义属性将被忽略。
1.4 多插槽内容投影
一个组件可以具有多个插槽,每个插槽可以指定一个 css 选择器,该选择器会决定将哪些内容放入该插槽。该模式称为多插槽内容投影。使用此模式,我们必须指定希望投影内容出现在的位置。可以通过使用 ng-content 的 select 属性来完成此任务。
组件模板含有多个 ng-content 标签。为了区分投影的内容可以投影到对应 ng-content 标签,需要使用 ng-content 标签上的 select 属性作为识别。select 属性支持标签名、属性、css 类和 :not 伪类的任意组合。不添加 select 属性的 ng-content 标签将作为默认插槽。所有未匹配的投影内容都会投影在该 ng-content 的位置。以 button 组件为例,创建一个多槽内容投影:
button-component.ts
@component({ selector: '[appbutton]', template: ` <span class="icon-search"></span> <ng-content select="[shuxing]"></ng-content> <ng-content select="p"></ng-content> <ng-content select=".lei"></ng-content>`})export class appbuttoncomponent {}
实际使用如下:
<button appbutton><p>click</p> <span shuxing>me</span> <span class="lei">here</span></button>
1.5 ngprojectas
在某些情况下,我们需要使用 ng-container 把一些内容包裹起来传递到组件中。大多数情况是因为我们需要使用结构型指令像 ngif 或者 ngswitch 等。。
在下面的例子中,我们将 header 包裹在了 ng-container 中。
@component({ selector: 'app-card', template: ` <div class="card"> <div class="header"> <ng-content select="header"></ng-content> </div> <div class="content"> <ng-content select="content"></ng-content> </div> <div class="footer"> <ng-content select="footer"></ng-content> </div> <ng-content></ng-content> </div>`})export class appcardcomponent {}
使用:
<app-card> <ng-container> <header> <h1>angular</h1> </header> </ng-container> <content>one framework. mobile & desktop.</content> <footer><b>super-powered by google </b></footer></app-card>
由于 ng-container 的存在,header 部分并没有被渲染到我们想要渲染的插槽中,而是渲染到了没有提供任何 selector 的 ng-content 中。
在这种情况下,我们可以使用 ngprojectas 属性。
在上面的 ng-container 加上这个属性,就可以按照我们的期望来渲染了。
<app-card> <ng-container ngprojectas='header'> <header> <h1>angular</h1> </header> </ng-container> <content>one framework. mobile & desktop.</content> <footer><b>super-powered by google </b></footer></app-card>
二、 有条件的内容投影如果你的元件需要有条件地渲染内容或多次渲染内容,则应配置该元件以接受一个 ng-template 元素,其中包含要有条件渲染的内容。
在这种情况下,不建议使用 ng-content 元素,因为只要元件的使用者提供了内容,即使该元件从未定义 ng-content 元素或该 ng-content 元素位于 ngif 语句的内部,该内容也总会被初始化。
使用 ng-template 元素,你可以让元件根据你想要的任何条件显式渲染内容,并可以进行多次渲染。在显式渲染 ng-template 元素之前,angular 不会初始化该元素的内容。
2.1 ng-container
既不是一个组件,也不是一个指令,仅仅是一个特殊的tag而已。 使用 ng-container 渲染所包含的模板内容,不包含自身。
angular代码片段<div> <ng-container> <p>my name is wyl.</p> <p>what is you name?</p> </ng-container></div>
浏览器调试窗口,可以发现 <ng-container> 标签消失了,并没有起任何作用<div> <p>my name is wyl.</p> <p>what is you name?</p></div>
使用场景,如下,在我们需要遍历或 if 判断 时,它可以承担一个载体的作用<ul> <ng-container *ngfor="let item of items"> <li>{{ item .name}}</li> <li>{{ item .age}}</li> <li>{{ item .sex}}</li> </ng-container></ul>
另外,ng 中常见错误之一的 for 和 if 不能写在同一标签上(在一个宿主元素上只能应用一个结构型指令),利用 ng-container 标签可以在实现功能的基础上减少层级的嵌套。
2.2 ng-template
先来看下面一段代码
<ng-template> <p> in template, no attributes. </p></ng-template><ng-container> <p> in ng-container, no attributes. </p></ng-container>
浏览器输出结果是:
in ng-container, no attributes.
即 <ng-template> 中的内容不会显示。当在上面的模板中添加 ngif 指令:
<ng-template [ngif]="true"> <p> ngif with a ng-template.</p></ng-template><ng-container *ngif="true"> <p> ngif with an ng-container.</p></ng-container>
浏览器输出结果是:
ngif with a ng-template.ngif with an ng-container.
2.3 ng-template 和 <ng-container> 的配合使用
<ng-container *ngif="showsearchbread; else tplsearchempty"> 暂时搜索不到您要的数据喔</ng-container><ng-template #tplsearchempty> 快快开始获取吧!</ng-template>
2.4 ngtemplateoutlet
插入 ng-template 创建的内嵌视图。 ngtemplateoutlet 是一个结构型指令,接收一个 templateref 类型的值;
<div *ngtemplateoutlet="tpl1"></div><ng-template #tpl1> <span>i am span in template {{title}}</span></ng-template>
*ngtemplateoutlet = "templaterefexp; content: contentexp "
templaterefexp: ng-template 元素的 #idcontextexp:可空参数
content 是一个对象,这个对象可以包含一个 $implicit 的 key 作为默认值, 使用时在 模板 中用 let-key 语句进行绑定
content 的非默认字段需要使用 let-templatekey=contentkey 语句进行绑定
使用如下:
@component({ selector: 'ng-template-outlet-example', template: ` <ng-container *ngtemplateoutlet="greet"></ng-container> <hr> <ng-container *ngtemplateoutlet="eng; context: mycontext"></ng-container> <hr> <ng-container *ngtemplateoutlet="svk; context: mycontext"></ng-container> <hr> <ng-template #greet><span>hello</span></ng-template> <ng-template #eng let-name><span>hello {{name}}!</span></ng-template> <ng-template #svk let-person="localsk"><span>ahoj {{person}}!</span></ng-template>`})class ngtemplateoutletexample { mycontext = {$implicit: 'world', localsk: 'svet'};}
2.5 利用 ngtemplateoutlet 进行内容投影
@component({ selector: 'app-card', template: ` <div class="card"> <div class="header"> <ng-container *ngtemplateoutlet="headertemplate; context: { $implicit: title, index: otherdate }"></ng-container> </div> </div>`})export class appcardcomponent { @contentchild('header', { static: true }) headertemplate: templateref<any>; public title = 'test'; public otherdate = { auth: 'me', name: 'appcard' };}
使用
<app-card> <ng-template #header let-label let-item="otherdate"> <h1>angular</h1> {{label}} (test) and {{otherdate | json}} ({auth: 'me', name: 'appcard'}) </ng-template></app-card>
更多编程相关知识,请访问:编程教学!!
以上就是聊聊angular中进行内容投影的方法的详细内容。