Structural directives are responsible for HTML layout. They shape or reshape the DOM’s structure, typically by adding, removing, or manipulating elements.

structure directive负责HTML布局,组成或者改变DOM结构,在结构中添加移除或者控制其他HTML元素。

As with other directives, you apply a structural directive to a host element. The directive then does whatever it’s supposed to do with that host element and its descendants.

structural指令也需要施加到host元素上,指令会对host和其子元素施加影响。

一个例子:

<div *ngIf=“hero” class=“name”>{{hero.name}}

the asterisk (*) is a convenience notation and the string is a microsyntax rather than the usual template expression. Angular desugars this notation into a marked-up <ng-template> that surrounds the host element and its descendants. Each structural directive does something different with that template.

这里的星号实际上是一个语法糖,后面的ngIf称之为microsyntax,即微语法。Angular会把进行解糖操作,替换成传统的<ng-template>实现。值得一提的是,后者也不会出现在最后生成的html代码里

注意命名规范:

Throughout this guide, you’ll see a directive spelled in both UpperCamelCase and lowerCamelCase. Already you’ve seen NgIf and ngIf. There’s a reason. NgIf refers to the directive class; ngIf refers to the directive’s attribute name.

NgIf是结构化指令的实现class,ngif是指令的属性名,应用在HTML代码里。

除了structural指令外,Angular常用的还有Component指令和属性指令两种。

  • A component manages a region of HTML in the manner of a native HTML element. Technically it’s a directive with a template.
  • An attribute directive changes the appearance or behavior of an element, component, or another directive. For example, the built-in NgStyle directive changes several element styles at the same time.

You can apply many attribute directives to one host element. You can only apply one structural directive to a host element.

structural指令和host元素是1:1关系,attribute指令和host元素可以是N:1关系。

NgIf takes a boolean expression and makes an entire chunk of the DOM appear or disappear.

<p *ngIf="true">Expression is true and ngIf is true.This paragraph is in the DOM.
</p>
<p *ngIf="false">Expression is false and ngIf is false.This paragraph is not in the DOM.
</p>

运行时渲染出来的html里面,根本没有*ngIf="false"的html元素:

ngif语法糖的解糖过程

原始代码:

<div *ngIf="hero" class="name">{{hero.name}}</div>

解糖之后:

<ng-template [ngIf]="hero"><div class="name">{{hero.name}}</div>
</ng-template>
  • The *ngIf directive moved to the <ng-template> element where it became a property binding,[ngIf].
  • The rest of the <div>, including its class attribute, moved inside the <ng-template> element.

Angular consumed the <ng-template> content during its actual rendering and replaced the <ng-template> with a diagnostic comment.

Angular渲染时,将<ng-template>替换成用于诊断目的的ng-reflect-ng-if.

ngfor的解糖过程

原始代码:

<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">({{i}}) {{hero.name}}
</div>

解糖之后:

<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"><div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>

At minimum NgFor needs a looping variable (let hero) and a list (heroes).

NgFor至少需要一个列表(heroes)和展开这个列表的变量(let hero).

什么是微语法 Microsyntax

The Angular microsyntax lets you configure a directive in a compact, friendly string.

使用微语法(一个字符串)配置结构性指令。微语法解析器把这个字符串里的内容解析成<ng-template>的属性:

  • The parser translates let hero, let i, and let odd into variables named let-hero, let-i, and let-odd.

  • As the NgFor directive loops through the list, it sets and resets properties of its own context object. These properties can include, but aren’t limited to, index, odd, and a special property named $implicit.

NgFor遍历list,在每次循环过程体内部设置它自己上下文对象的属性,比如index,odd和$implicit.

Template input variable

A template input variable is a variable whose value you can reference within a single instance of the template. 可以在模板的某一个具体实例内被使用。

You declare a template reference variable by prefixing the variable name with # (#var). 通过#定义模板引用变量,指向它依附于的元素,组件或指令。整个模板内都可以访问。

A reference variable refers to its attached element, component or directive. It can be accessed anywhere in the entire template.

Template input and reference variable names have their own namespaces. The hero in let hero is never the same variable as the hero declared as #hero - 二者有各自的命名空间。

<ng-template>里面包含的元素不会出现在最后的HTML页面里:


为什么要使用ng-template, 而不重用div,span这些HTML原生的container元素?

Introducing another container element—typically a <span> or <div>—to group the elements under a single root is usually harmless. Usually … but not always.

如果应用程序里恰巧有css样式施加到<span>或者<div>上,此时再用二者作为structural指令的host元素就不太合适了,比如下面这个例子:

<p>I turned the corner<span *ngIf="hero">and saw {{hero.name}}. I waved</span>and continued on my way.
</p>

如果正好有css样式施加到span上:

p span { color: red; font-size: 70%; }

最后的布局就很怪异:

some HTML elements require all immediate children to be of a specific type. For example, the <select> element requires <option> children. You can’t wrap the options in a conditional <div> or a <span>.

还有一种情况,某些html元素要求其子元素必须是一种特殊的类型,比如<select>的子元素必须是<option>, 二者中间不能再引入<div>或者<span>等中间层级。

像下图这种设计,最后是看不到下拉菜单的:

<div>Pick your favorite hero(<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)
</div>
<select [(ngModel)]="hero"><span *ngFor="let h of heroes"><span *ngIf="showSad || h.emotion !== 'sad'"><option [ngValue]="h">{{h.name}} ({{h.emotion}})</option></span></span>
</select>

解决方案是采用ng-container:

The Angular <ng-container> is a grouping element that doesn’t interfere with styles or layout because Angular doesn’t put it in the DOM.

是一种grouping element,不会干预HTML正常的布局和样式,因为Angular不会将其渲染到最终的HTML中去。

<div>Pick your favorite hero(<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)
</div>
<select [(ngModel)]="hero"><ng-container *ngFor="let h of heroes"><ng-container *ngIf="showSad || h.emotion !== 'sad'"><option [ngValue]="h">{{h.name}} ({{h.emotion}})</option></ng-container></ng-container>
</select>

注意,要使用ngModel指令,必须先import FormsModule.

The <ng-container> is a syntax element recognized by the Angular parser. It’s not a directive, component, class, or interface. It’s more like the curly braces in a JavaScript if-block.

Angular解析器能够识别<ng-container>这个语法元素,后者并不是一个指令,也非Component,class或者interface. <ng-container>和JavaScript里的if block很类似:

if (someCondition) {statement1;statement2;statement3;
}

Without those braces, JavaScript would only execute the first statement when you intend to conditionally execute all of them as a single block. The <ng-container> satisfies a similar need in Angular templates.

要获取更多Jerry的原创文章,请关注公众号"汪子熙":

2020国庆节 Angular structual 指令学习笔记(<ng-template>) 包含语法糖解糖过程相关推荐

  1. Angular官网学习笔记

    Angular官网学习笔记 一.Angular概述 **什么是Angular:**一个基于TypeScript构建的开发平台包括: 一个基于组件的框架,用于构建可伸缩的Web应用 一组完美集成的库,涵 ...

  2. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  3. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

  4. RISC-V 指令学习笔记(基于CH32V103)

    文章目录 RISC-V 指令学习笔记(基于CH32V103) 一.指令结构分类 二.寄存器功能 三.加载存储指令 四.算数运算指令 五.移位指令 六.逻辑操作指令 七.跳转指令 7.1 条件跳转 7. ...

  5. JDBC学习笔记02【ResultSet类详解、JDBC登录案例练习、PreparedStatement类详解】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  6. Kotlin学习笔记(3)- 语法

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  7. 设计模式学习笔记——模板(Template)模式

    设计模式学习笔记--模板(Template)模式 @(设计模式)[设计模式, 模板模式, template, 模板方法] 设计模式学习笔记模板Template模式 基本介绍 模板案例 类图 实现代码 ...

  8. 小猫爪:i.MX RT1050学习笔记26-RT1xxx系列的FlexCAN详解

    i.MX RT1050学习笔记26-RT1xxx系列的FlexCAN详解 1 前言 2 FlexCAN简介 2.1 MB(邮箱)系统 2.1.1 正常模式下 2.1.2 激活了CAN FD情况下 2. ...

  9. Python学习笔记 —— 独步天下推导式语法糖

    Python学习笔记 -- 独步天下推导式语法糖 前言 介绍 列表推导式 获取当月天数 字典推导式 模拟三条用户数据 结束语 前言 最近心血来潮,学习了一下Python,其中关于 推导式语法糖 感觉功 ...

最新文章

  1. 微型计算机2020年6月上,2020年1-6月全国微型计算机设备产量统计分析
  2. gitlab 钩子 php,gitlab通过webhook.php自动部署标签
  3. android怎么关应用程序,如何关闭Android应用程序?
  4. 模板参数仅作为函数的返回值
  5. 1.3 函数调用反汇编解析以及调用惯例案例分析
  6. Core Services层
  7. android 设置线程优先级
  8. Fatal error: Cannot redeclare db_connect() 错误
  9. iOS开发之千位分隔符(千位符)
  10. Android中View的绘制过程 onMeasure方法简述 附有自定义View例子
  11. Origin8画图:画百分比堆积柱形图
  12. 2019冬令营集训1月7-10日总结
  13. 英雄无敌6服务器在哪个文件夹,英雄无敌6无法进入游戏解决方法_单机攻略_快吧单机游戏...
  14. 基于babylon3D模型研究3D骨骼动画(1)
  15. matlab读取wav文件出错,MATLAB读取wav文件
  16. python里str什么意思_python中str是什么意思
  17. java-php-python-ssm基于移动端的选课系统的设计与实现服务器端计算机毕业设计
  18. 好消息:部分银行磁条卡更换芯片卡
  19. 四年嵌入式技术沉淀,处女作《STM32CubeMX系列实战教程》诞生
  20. 怎么将sql文件加载到数据库

热门文章

  1. 快速安装LNMP环境
  2. 关于 PHP 5.4 你所需要知道的
  3. 《软件需求最佳实践》阅读笔记01
  4. SSL 1760——商店选址问题(最短路)
  5. 通过一般处理程序实现【文件上传】
  6. 用为知发布博客到博客园、使用Wiz编写和发布博客园(cnblogs)博客
  7. 【转】如何更改VS2010的[默认开发语言]默认环境设置 .
  8. [转]Vi/Vim查找替换使用方法
  9. jacoco + junit + mock 单测没有统计覆盖率问题
  10. 基于KD树的K近邻算法(KNN)算法