2020国庆节Angular structual指令学习笔记

时间:2022-07-26
本文章向大家介绍2020国庆节Angular structual指令学习笔记,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

修改用户页面完成后,点击“确认”按钮,界面没有任何反应,用户也不知道修改成功与否。

只有点击f12打开Chrome开发者工具,观察eduser API的响应:

在response里看到status code为0,interpret字段为“修改成功”,才知道确认按钮点击之后修改确实生效了。这个bebavior对普通老百姓很不友好。

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 that surrounds the host element and its descendants. Each structural directive does something different with that template.

这里的星号实际上是一个语法糖,后面的ngIf称之为microsyntax,即微语法。Angular会把进行解糖操作,替换成传统的实现。值得一提的是,后者也不会出现在最后生成的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 element where it became a property binding,[ngIf].
  • The rest of the , including its class attribute, moved inside the element.

Angular consumed the content during its actual rendering and replaced the with a diagnostic comment.

Angular渲染时,将替换成用于诊断目的的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.

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

  • 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 - 二者有各自的命名空间。

里面包含的元素不会出现在最后的HTML页面里:

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

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

如果应用程序里恰巧有css样式施加到或者

上,此时再用二者作为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 element requires children. You can’t wrap the options in a conditional or a .

还有一种情况,某些html元素要求其子元素必须是一种特殊的类型,比如的子元素必须是, 二者中间不能再引入

或者等中间层级。

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

<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 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 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解析器能够识别这个语法元素,后者并不是一夜指令,也非Component,class或者interface. 和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 satisfies a similar need in Angular templates.