Skip to content
On this page

指令

ng 的指令允许你向 HTML 元素中添加定制功能。非组件指令(组件是一种特殊的指令)通常对现有元素进行修改,进一步可分为两种类型:

  • 属性指令

    属性指令可改变元素或者组件的外观、样式和行为。比如 ngClassngStyle 用于绑定样式。

  • 结构化指令

    结构化指令,可通过控制元素的渲染,来改变页面的布局。比如 ngIfngFor

内置属性指令

通常我们使用类名来称呼指令,所以我们在书写指令时,使用的是大驼峰的风格,比如 NgClass。而在使用时,采用小驼峰的形式,比如 <div [ngClass]="myClass"></div>

NgClassNgStyle 是两个处理样式的内置指令,使用它们,可灵活地绑定元素或者组件的样式,类似于 vue 中的 classstyle

class 属性绑定的缺点?

当需要根据条件来绑定多个类时,我们需要根据条件来生成多个字符串,随着条件的增加,代码变得不好维护,而 NgClass 可解决这一问题。

NgClass 接收一个对象作为输入,键是一个类名,而键值是布尔。 键值为假值, ng 会把对应的键从元素 class 属性中删除,为真值则把对应的键添加到 class 属性中。

NgClass 在使用时,可以和元素的 class 属性一起使用,NgClass 不会覆盖原来的 class,而是智能合并。

在元素应用不同类的情况时,NgClass 容易计算和理解,容易进行单元测试。

NgStyle和 NgClass 非常相似,接收一个对象,对象的键时 CSS 属性,键值是 CSS 属性值,也可是一个表达式,ng 会把对象编译成行内样式,这和 Vue 的 style 极为相似。

html
h3 [ngStyle]="nameStyle">{{stock.name}}</h3>

TS 代码

ts
this.nameStyle = {
	color: "red",
	width: largeChange ? "150px" : "150px",
	"font-size": "1.5em",
	backgroundColor: "yellow",
};

在书写有-的样式属性时,需要转为小驼峰式或者引号包裹原来的属性。

内联样式的绑定语法,需要写很多代码,当样式很多时,会比较繁琐,不推荐这种写法。

绑定样式的另一种写法:

html
[class.class-name]="expression" [style.css-property]="expression"

当表达式为真值时,类名或者 css 属性会应用到元素上。


结构化指令

结构化指令可控制 DOM 元素的渲染,从而改变页面的布局。

结构化指令遵循一种特殊的语法--- 以 * 开头,很容易和属性绑定和事件绑定区分。

常见的结构化指令:

  • NgIf --- 条件渲染。
  • NgSwitch --- 多条件渲染。
  • NgFor --- 渲染列表。
html
<h1 *ngIf="showTitle">hello {{title}}</h1>
<hr />
<ul [ngSwitch]="howAreYou">
	<li *ngSwitchCase="'great'">great</li>
	<li *ngSwitchCase="'good'">good</li>
	<li *ngSwitchCase="'notBad'">notBad</li>
	<li *ngSwitchCase="'bad'">bad</li>
	<li *ngSwitchDefault>well</li>
</ul>
<hr />
<ul>
	<li *ngFor="let item of list;let i = index;trackBy:trackByMethod">
		{{i}} -- {{item}} -- {{trackBy}}
	</li>
</ul>

NgSwitch 实际上不是一个结构指令,而是属性指令,和 JS 里的 switch 语法类似,有一个 NgSwitchCaseNgSwitchDefault 结合使用,该指令类似 vue 中的 v-if v-else-if v-else

NgFor 用于循环渲染列表元素,表达式是一个 of 循环,可通过另外一个语句获取元素的下标,可提供一个 trackBy 来追踪每个元素,在列表重新渲染时,会根据它来决定是否重用 DOM ,从而提高性能,它接收一个函数,该函数返回一个唯一的值,提供给 ng 用来追踪元素。类似 vue 中 v-for 中的 key。

可以把 ngFor 和 ngIf 同时用在一个元素上吗?

ng 不支持多个指令用到同一个元素上,因为这样会不清楚哪个指令先执行,ng 是禁止这样做的,否则报错。

使用 ng-container 包裹希望条件渲染的元素。

有如下数组,想要渲染 isGood 为 true 的元素,可以这样写:

ts
[
	{ tech: "jquery", isGood: true },
	{ tech: "angular", isGood: true },
	{ tech: "react", isGood: false },
	{ tech: "vue", isGood: false },
];
html
<ul>
	<ng-container *ngFor="let item of list">
		<li *ngIf="item.isGood">{{item.tech}}</li>
	</ng-container>
</ul>

更多阅读:

Angular ng-template, ng-container and ngTemplateOutlet - The Complete Guide To Angular Templates

How To Use the ng-container Element in Angular

https://stackoverflow.com/questions/39547858/ng-container-vs-template

https://www.freecodecamp.org/news/everything-you-need-to-know-about-ng-template-ng-content-ng-container-and-ngtemplateoutlet-4b7b51223691/

项目报错:Can't bind to 'ngForOf' since it isn't a known property of 'ng-container'. 然后报错消失,奇怪。

如何写自定义指令?

Released under the MIT License.