高级 Angular 组件模式 (6)

06 Use <ng-template>

Render Props最近在React社区中引发了轰动,可是与之相似的模式在Angular中彷佛并无获得太多关注。我在以前写的文章说起过,TemplateRefs就是Angular中的Render Props,同时我会在这篇文章中列举一个简单易用的例子。html

Note: TemplateRef是一个类名而 <ng-template>是一个 html标签,它们本质上是相同的。不过你可能会在项目中更频繁地使用 <ng-template>,可是在网上你能够很容易的搜索到关于 TemplateRef的知识,由于 <ng-template>会给你提供不少 html5中的 <template>标签的信息。

咱们已有的实现中,使用自定义内容指令(content directives)。当组件做者提早了解使用该toggle组件的父组件所须要的状态时,那么它将会正常的运做。可是若是父组件所须要的状态并不在咱们的设想以内,咱们该怎么办?前端

目标

toggle组件的状态直接提供给父组件,同时容许父组件提供相应的渲染视图(view)。html5

实现

<ng-template>组件能够完美地解决问题。react

1. Toggle 组件

<toggle>组件可以经过ContentChild装饰器获得关于<ng-template>的引用,以后会赋予模板在渲染时所须要的状态,代码以下:设计模式

<ng-container
  *ngTemplateOutlet="layoutTemplate; context: { on: this.on, toggle: this.toggle, fns: { toggle: this.toggle } }">
</ng-container>

这里<ng-container>被当作一个占位符来使用,以后你可使用*ngTemplateOutlet指令来填充它,layoutTemplate变量指代的是须要被渲染的模板,context对象包含的键值对会做为组件状态注入layoutTemplate中。性能

2. 父组件

toggle组件中传入的状态是经过let关键字在父组件的<ng-template>标签上显示声明的。测试

let关键字的使用方式类是这样的:let-templatevar="inputvar"templatevar指代在<ng-template>标签中,关联组件状态值的变量名,而inputvar指代使用<toggle>组件的模板做用域中的变量名。this

这种语法会有效地避免命名冲突,好比在父组件做用域中已经有一个inputvar变量了。设计

成果

stackblitz演示地址code

译者注

这种组件设计模式按我我的的理解,实际上是依赖倒置原则在视图渲染层的一种延伸,为何这么说呢?是由于一般状况下子组件视图的渲染逻辑取决于传入的props状态和自身提供的模板,这在大多数状况下不会形成任何困扰,可是当咱们没法在提早得知咱们须要渲染什么的时候,这个问题就会变得十分棘手。

一种解决方法,咱们可使用条件渲染指令,根据传入的状态来断定组件渲染的状态,这种解决方法在状况比较少的状况下是能够解决问题的,可是当状况数量十分庞大的状况下,增长过多的条件断定会导致子组件的模板代码量剧增,同时下降性能,由于每次渲染都会进行若干次条件逻辑判断。

除了上面的解决方法,就是使用正文中所说起的模式了,这种模式将子组件视图的渲染逻辑倒置为子组件仅仅声明模板中所会使用的状态变量,对于这些变量和模板的注入工做,全权赋予父组件,所以会使子组件的复用性和可测试性大大提升。

正文中仅列举了一个简单的例子中,我这里在简单说起一个实际工做可能会用到的例子,就是表单校验的错误提示组件,通常前端组件设计但凡涉及表单,都会是十分复杂的,更不用说校验这种灵活性很高的功能了。

为了适应表单校验的灵活性,咱们使用这种模式会事半功倍,提供校验信息的组件仅仅声明渲染表单错误提示信息须要设计的状态变量便可,好比dirtytouched等等,对于错误信息的文案及样式,通通交由错误提示组件的使用者完成。

相关文章
相关标签/搜索