Angular 向组件传递模板的两种方法


Posted in Javascript onFebruary 23, 2018

最近在写一个日期选择器组件,为了满足将来可能出现的各种需求,所以需要能够高度的自定义组件的样式。为了达到这个目的,需要能够在日期选择器组件外控制每个日期格子内要显示的内容,比如,标上节假日之类的。这时候,组件的一部分模板就需要由调用方提供。

在 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 可以向传入的模板传递渲染数据,两者搭配使用可以起到很好的效果。

以上所述是小编给大家介绍的Angular 向组件传递模板的两种方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Javascript 写的简单进度条控件
Jan 22 Javascript
jquery限定文本框只能输入数字即整数和小数
Nov 29 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
Jan 15 Javascript
jQuery 弹出层插件(推荐)
May 24 Javascript
浅谈js中调用函数时加不加括号的问题
Jul 28 Javascript
AngularJS 依赖注入详解和简单实例
Jul 28 Javascript
AngularJS基础 ng-value 指令简单示例
Aug 03 Javascript
原JS实现banner图的常用功能
Jun 12 Javascript
详解VueRouter进阶之导航钩子和路由元信息
Sep 13 Javascript
学习node.js 断言的使用详解
Mar 18 Javascript
微信小程序事件 bindtap bindinput代码实例
Aug 26 Javascript
js实现直播点击飘心效果
Aug 19 Javascript
详解Node.js中的Async和Await函数
Feb 22 #Javascript
解决webpack无法通过IP地址访问localhost的问题
Feb 22 #Javascript
webpack-dev-server远程访问配置方法
Feb 22 #Javascript
关于Webpack dev server热加载失败的解决方法
Feb 22 #Javascript
基于webpack-hot-middleware热加载相关错误的解决方法
Feb 22 #Javascript
解决Webpack 热部署检测不到文件变化的问题
Feb 22 #Javascript
webpack-dev-server自动更新页面方法
Feb 22 #Javascript
You might like
一个阿拉伯数字转中文数字的函数
2006/10/09 PHP
浏览器关闭后,能继续执行的php函数(ignore_user_abort)
2012/08/01 PHP
PHP flock 文件锁详细介绍
2012/12/29 PHP
php获取当月最后一天函数分享
2015/02/02 PHP
php中动态变量用法实例
2015/06/10 PHP
PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】
2018/04/27 PHP
Javascript 变量作用域 两个可能会被忽略的小特性
2010/03/23 Javascript
ImageZoom 图片放大镜效果(多功能扩展篇)
2010/04/14 Javascript
js判断变量是否未定义的代码
2020/03/28 Javascript
JS实现的数组全排列输出算法
2015/03/19 Javascript
Node.js项目中调用JavaScript的EJS模板库的方法
2016/03/11 Javascript
基于Vue2.0的分页组件
2017/03/16 Javascript
JS+CSS实现下拉刷新/上拉加载插件
2017/03/31 Javascript
利用Jasmine对Angular进行单元测试的方法详解
2017/06/12 Javascript
vue实现未登录跳转到登录页面的方法
2018/07/17 Javascript
关于vue v-for 循环问题(一行显示四个,每一行的最右边那个计算属性)
2018/09/04 Javascript
layer.js open 隐藏滚动条的例子
2019/09/05 Javascript
js实现图片上传即时显示效果
2019/09/30 Javascript
[04:52]DOTA2亚洲邀请赛附加赛 TOP10精彩集锦
2015/01/29 DOTA
[01:04]DOTA2上海特锦赛现场采访 FreeAgain遭众解说围攻
2016/03/25 DOTA
详解Python中DOM方法的动态性
2015/04/11 Python
Python基于高斯消元法计算线性方程组示例
2018/01/17 Python
PyCharm GUI界面开发和exe文件生成的实现
2020/03/04 Python
使用pandas读取表格数据并进行单行数据拼接的详细教程
2021/03/03 Python
美国购买当代和现代家具网站:MODTEMPO
2018/07/20 全球购物
Nike澳大利亚官网:Nike.com (AU)
2019/06/03 全球购物
新加坡第一大健康与美容零售商:屈臣氏新加坡(Watsons Singapore)
2020/12/11 全球购物
机电专业体育教师求职信
2013/09/21 职场文书
光电信息专业应届生求职信
2013/10/07 职场文书
中学教师自我鉴定
2014/02/07 职场文书
会计岗位描述
2014/02/22 职场文书
《果园机器人》教学反思
2014/04/13 职场文书
小学先进集体事迹材料
2014/05/31 职场文书
党的群众路线教育实践活动制度建设计划方案
2014/10/31 职场文书
孝老爱亲事迹材料
2014/12/24 职场文书
Python中Cookies导出某站用户数据的方法
2021/05/17 Python