本篇文章带大家聊聊angular中的内容投影,介绍一下使用ng-content进行内容投影的方法,并了解有条件内容投影的实现方法,希望对大家有所帮助!
一、ng-content进行内容投影
1.1ng-content
ng-content元素是一个用来插入外部或者动态内容的占位符。父组件将外部内容传递给子组件,当Angular解析模板时,就会在子组件模板中ng-content出现的地方插入外部内容。
我们可以使用内容投影来创建可重用的组件。这些组件有相似的逻辑和布局,并且可以在许多地方使用。一般我们在封装一些公共组件的时候经常会用到。
1.2 为什么使用内容投影
定义一个 button 组件:
button-component.ts
@Component({selector:'[appButton]',template:`<spanclass="icon-search"></span>`})exportclassAppButtonComponent{}
这个 button 组件的目的是在按钮内部加一个搜索的图标,我们实际使用如下:
<buttonappButton>click</button>
我们发现组件只会展示搜索图标, 按钮的文本不会展示,能你会想到最常使用的@Input装饰器,但是如果我们不只是想传文本进来,而是传一段html进来呢?此时就会用到ng-content。
1.3 单插槽内容投影
内容投影的最基本形式是单插槽内容投影。
单插槽内容投影是指创建一个组件,我们可以在其中投影一个组件。
以 button 组件为例,创建一个单槽内容投影:
button-component.ts
@Component({selector:'[appButton]',template:`<spanclass="icon-search"></span><ng-content></ng-content>`})exportclassAppButtonComponent{}
实际使用如下:
<buttonappButton>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:`<spanclass="icon-search"></span><ng-contentselect="[shuxing]"></ng-content><ng-contentselect="p"></ng-content><ng-contentselect=".lei"></ng-content>`})exportclassAppButtonComponent{}
实际使用如下:
<buttonappButton><p>click</p><spanshuxing>me</span><spanclass="lei">here</span></button>
1.5ngProjectAs
在某些情况下,我们需要使用ng-container把一些内容包裹起来传递到组件中。大多数情况是因为我们需要使用结构型指令像ngIf或者ngSwitch等。。
在下面的例子中,我们将header包裹在了ng-container中。
@Component({selector:'app-card',template:`<divclass="card"><divclass="header"><ng-contentselect="header"></ng-content></div><divclass="content"><ng-contentselect="content"></ng-content></div><divclass="footer"><ng-contentselect="footer"></ng-content></div><ng-content></ng-content></div>`})exportclassAppCardComponent{}
使用:
<app-card><ng-container><header><h1>Angular</h1></header></ng-container><content>Oneframework.Mobile&desktop.</content><footer><b>Super-poweredbyGoogle</b></footer></app-card>
由于ng-container的存在,header部分并没有被渲染到我们想要渲染的插槽中,而是渲染到了没有提供任何selector的ng-content中。
在这种情况下,我们可以使用ngProjectAs属性。
在上面的ng-container加上这个属性,就可以按照我们的期望来渲染了。
<app-card><ng-containerngProjectAs='header'><header><h1>Angular</h1></header></ng-container><content>Oneframework.Mobile&desktop.</content><footer><b>Super-poweredbyGoogle</b></footer></app-card>
二、 有条件的内容投影
如果你的元件需要有条件地渲染内容或多次渲染内容,则应配置该元件以接受一个ng-template元素,其中包含要有条件渲染的内容。
在这种情况下,不建议使用ng-content元素,因为只要元件的使用者提供了内容,即使该元件从未定义ng-content元素或该ng-content元素位于ngIf语句的内部,该内容也总会被初始化。
使用ng-template元素,你可以让元件根据你想要的任何条件显式渲染内容,并可以进行多次渲染。在显式渲染ng-template元素之前,Angular不会初始化该元素的内容。
2.1ng-container
既不是一个组件,也不是一个指令,仅仅是一个特殊的tag而已。 使用ng-container渲染所包含的模板内容,不包含自身。
angular代码片段
<div><ng-container><p>Mynameiswyl.</p><p>Whatisyouname?</p></ng-container></div>
浏览器调试窗口,可以发现<ng-container>标签消失了,并没有起任何作用
<div><p>Mynameiswyl.</p><p>Whatisyouname?</p></div>
使用场景,如下,在我们需要遍历或if 判断时,它可以承担一个载体的作用
<ul><ng-container*ngFor="letitemofitems"><li>{{item.name}}</li><li>{{item.age}}</li><li>{{item.sex}}</li></ng-container></ul>
另外,ng中常见错误之一的for和if不能写在同一标签上(在一个宿主元素上只能应用一个结构型指令),利用ng-container标签可以在实现功能的基础上减少层级的嵌套。
2.2ng-template
先来看下面一段代码
<ng-template><p>Intemplate,noattributes.</p></ng-template><ng-container><p>Inng-container,noattributes.</p></ng-container>
浏览器输出结果是:
Inng-container,noattributes.
即<ng-template>中的内容不会显示。当在上面的模板中添加ngIf指令:
<ng-template[ngIf]="true"><p>ngIfwithang-template.</p></ng-template><ng-container*ngIf="true"><p>ngIfwithanng-container.</p></ng-container>
浏览器输出结果是:
ngIfwithang-template.ngIfwithanng-container.
2.3ng-template和<ng-container>的配合使用
<ng-container*ngIf="showSearchBread;elsetplSearchEmpty">暂时搜索不到您要的数据喔</ng-container><ng-template#tplSearchEmpty>快快开始获取吧!</ng-template>
2.4ngTemplateOutlet
插入ng-template创建的内嵌视图。ngTemplateOutlet是一个结构型指令,接收一个TemplateRef类型的值;
<div*ngTemplateOutlet="tpl1"></div><ng-template#tpl1><span>Iamspanintemplate{{title}}</span></ng-template>*ngTemplateOutlet="templateRefExp;content:contentExp"
templateRefExp:ng-template元素的#ID
contextExp:
可空参数
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#englet-name><span>Hello{{name}}!</span></ng-template><ng-template#svklet-person="localSk"><span>Ahoj{{person}}!</span></ng-template>`})classNgTemplateOutletExample{myContext={$implicit:'World',localSk:'Svet'};}
2.5 利用ngTemplateOutlet进行内容投影
@Component({selector:'app-card',template:`<divclass="card"><divclass="header"><ng-container*ngTemplateOutlet="headerTemplate;context:{$implicit:title,index:otherDate}"></ng-container></div></div>`})exportclassAppCardComponent{@ContentChild('header',{static:true})headerTemplate:TemplateRef<any>;publictitle='Test';publicotherDate={auth:'me',name:'appCard'};}
使用
<app-card><ng-template#headerlet-labellet-item="otherDate"><h1>Angular</h1>{{label}}(Test)and{{otherDate|json}}({auth:'me',name:'appCard'})</ng-template></app-card>
产品猿社区致力收录更多优质的商业产品,给服务商以及软件采购客户提供更多优质的软件产品,帮助开发者变现来实现多方共赢;
日常运营的过程中我们难免会遇到各种版权纠纷等问题,如果您在社区内发现有您的产品未经您授权而被用户提供下载或使用,您可按照我们投诉流程处理,点我投诉;
本文来自用户发布投稿,不代表产品猿立场 ;若对此文有疑问或内容有严重错误,可联系平台客服反馈;
部分产品是用户投稿,可能本文没有提供官方下下载地址或教程,若您看到的内容没有下载入口,您可以在我们产品园商城搜索看开发者是否有发布商品;若您是开发者,也诚邀您入驻商城平台发布的产品,地址:点我进入;
如若转载,请注明出处:https://www.chanpinyuan.cn/28794.html;