Angular 向组件传递模板的几种方法
2018-02-23 02:41
603 查看
最近在写一个日期选择器组件,为了满足将来可能出现的各种需求,所以需要能够高度的自定义组件的样式。为了达到这个目的,需要能够在日期选择器组件外控制每个日期格子内要显示的内容,比如,标上节假日之类的。这时候,组件的一部分模板就需要由调用方提供。
在 React 里面,这种需求挺简单的,只要实现一个
第一种方式
假设我们有一个上述的组件,然后向下面这样调用:
那么最终的渲染结果将会是这样的:
看起来就是发生了很简单的替换,但是如果在
然后像下面这样使用:
最终的渲染结果将会是这样:
除了设置
这次被传入的模板变成了一个
第二种方式
使用
就是这么简单的改动就可以让我们的组件从外界接受模板了,来试一试:
参考:
ng-content: The hidden docs
在 React 里面,这种需求挺简单的,只要实现一个
date => Element这样的函数就好了,但是 Angular 模板是纯粹的模板,需要使用一些专门的概念才能实现这个功能。
第一种方式 <ng-content>
<ng-content>这个标签到本文撰写时为止,还没有官方的文档,甚至连占位符都没有。但是这并不妨碍我们的使用,外国热心网友已经总结出了
<ng-content>在现阶段的特点与作用。
基本用法
<!-- Wrapper.Component.html --> <div> hello <ng-content></ng-content> </div>
假设我们有一个上述的组件,然后向下面这样调用:
<wrapper> <span> World </span> </wrapper>
那么最终的渲染结果将会是这样的:
<div> hello <span> World </span> </div>
看起来就是发生了很简单的替换,但是如果在
Wrapper中出现了多个
<ng-content>会出现多个
<span> World </span>吗?答案是不会的。
<ng-content>的本质只是移动元素,并不会去自动的创建传入的模板,所以就算用
ngFor套住
<ng-content>也不会出现很多个
<span> World </span>。如果传入的是自定义的组件,这些组件也只会被实例化一次。
进阶用法
当然,如果<ng-content>的功能仅仅只是这样就显得太鸡肋了,在使用
<ng-content>的时候可以指定一个选择器,这个选择器可以捕获相符的直接子元素。例如:
<!-- Wrapper.Component.html --> <div> hello <ng-content></ng-content> <hr/> <ng-content select="span"></ng-content> </div>
然后像下面这样使用:
<wrapper> <span> World </span> 2333 </wrapper>
最终的渲染结果将会是这样:
<div> hello 2333 <hr/> <span> World </span> </div>
除了设置
ng-content标签的
select属性之外,还可以在子元素上使用
ngProjectAs属性,这个属性可以让这个元素被父元素中指定的
ng-content所捕获。举个例子:
<wrapper> <div ngProjectAs="span"> World </div> 2333 </wrapper>
这次被传入的模板变成了一个
div,但是因为设置了
ngProjectAs,所以“World”会出现在分割线下方。
第二种方式 NgTemplateOutlet
指令
使用 ng-content确实可以起到传入模板的效果,但是却有个很致命的问题,就是无法传递数据到传入的模板中。为了将数据传递到传入的模板中,就需要使用到
NgTemplateOutlet指令。
基本使用
这个指令可以用来在模板的指定位置实例化一个TemplateRef对象,同时,在实例化的过程中还可以传入一个数据对象。而
TemplateRef可以通过
ng-template标签来创建,举个例子:
@Component({ selector: 'ng-template-outlet-example', template: ` <ng-container *ngTemplateOutlet="name; context: myContext"></ng-container> <ng-template #name let-name="data"><span>Hello {{name}}!</span></ng-template> ` }) class NgTemplateOutletExample { myContext = {data: 'World'}; }
ng-container是一个虚拟的元素,在这个元素上我们使用了一个
NgTemplateOutlet指令,指定了要实例化下面的名为
name的
ng-template。同时把
myContext这个对象作为实例化的数据上下文传入,所以最终就会显示 “Hello World!”。值得注意的是在
ng-template里面获取传输的数据上下文的方式:
let-variableName='key'。
进阶使用
接下来就要实现本文开头提到的需求了,在组件外部传入模板。还是以上面的例子为例,因为模板需要由外界作为子内容传入,所以需要我们手动来捕获模板,这里需要就需要使用ContentChild:
@Component({ selector: 'wrapper', template: ` <ng-container *ngTemplateOutlet="name; context: myContext"></ng-container> ` }) class NgTemplateOutletExample { @ContentChild(TemplateRef) name: TemplateRef<any>; myContext = {data: 'World'}; }
就是这么简单的改动就可以让我们的组件从外界接受模板了,来试一试:
<wrapper> <ng-template let-value="data"> <span>Hello {{value}}!</span> </ng-template> </wrapper>
总结
以上就是 Angular 中向组件传递模板的两种方法,其中,使用<ng-content>标签可以更方便的控制传入的模板在 DOM 中的位置,而
NgTemplateOutlet可以向传入的模板传递渲染数据,两者搭配使用可以起到很好的效果。
参考:
ng-content: The hidden docs
相关文章推荐
- Angular 向组件传递模板的两种方法
- Angular利用内容投射向组件输入ngForOf模板的方法
- angular模块和组件之间传递信息和操作流程的方法(笔记)
- Angular5.0 子组件通过service传递值给父组件的方法
- angular6.0使用教程之父组件通过url传递id给子组件的方法
- react 父组件与子组件之间的值传递的方法
- [ExtJS5学习笔记]第七节 Extjs5的组件components及其模板事件方法学习
- vue2.0 兄弟组件数据传递方法
- vuejs动态组件给子组件传递数据的方法详解
- Django模板变量如何传递给外部js调用的方法小结
- vue组件间的数据和方法传递
- C#和asp.net中链接数据库中 参数的几种传递方法
- 组件协作模式--Tmplate Method模板方法
- ASP.NET页面之间传递值的几种方法<转>
- Android中Activity之间数据传递的几种方法总结
- Asp.net页面之间传递参数的几种方法
- 几种数组排序方法及二维数组作参数传递
- VC/MFC子窗体向父窗体传递参数的几种方法
- Angular2组件开发—为模板应用样式(二)
- vue中各组件之间传递数据的方法示例