# 三種 Angular 指令 (Directives)
# 元件型指令
component
# 屬性型指令
修改元素的外觀或行為 - NgStyle, NgClass
*常使用 NgClass
# 結構型指令 (Structure Directives) - 新增或刪除 DOM 改變 DOM 結構
NgIf, NgFor, NgSwitch 來控制 DOM 結構
*ngSwitch 前不加星號*ngIf, ngFor, ngSwitchDefault, ngSwitchCase 前加星號
# 元件型指令
先打開終端機並建立一個 footer 的 component
ng g c footer
然後把 app.component.html 裡面的 footer 搬到 footer.component.html 裡面
footer.component.html
<footer class="footer">...</footer>
再到 app.component.html 引入 footer
...
<!-- 元件型指令(directive) -->
<app-footer></app-footer>
到 footer.component.ts 看元件的內容
import { Component, OnInit } from "@angular/core";
// @ decorator 宣告一個元件
@Component({
// 在 html 的 tag
selector: "app-footer",
// template 路徑
templateUrl: "./footer.component.html",
// template 另外一種寫法(不建議)
/* template:`
<div>
<span>Footer</span>
</div>
` */
// scss 路徑
// 這邊的樣式只會套用在自己的元件,因為 Angular 會給一個 attr 綁定在樣式裡面
/* 如.footer[_ngcontent-kwl-c49] p[_ngcontent-kwl-c49] {
color: yellow;}
*/
styleUrls: ["./footer.component.scss"],
// 若不想加 attr 在樣式表內
// encapsulation:ViewEncapsulation.Emulated > 預設值
// .footer p { color: yellow; }
encapsulation: ViewEncapsulation.None,
})
export class FooterComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
}
# 屬性型指令
# NgStyle, NgClass
NgStyle 範例一
首先在 header.component.ts 建立變數 counter 並在 changeTitle() 觸發時讓 counter++
export class HeaderComponent implements OnInit {
title = "demo";
url = "http://blog.miniasp.com/";
counter = 0;
constructor() {}
changeTitle(altKey: boolean) {
if (altKey) {
this.title = "change title click";
}
this.counter++;
}
ngOnInit(): void {}
}
header.component.html
在 subtitle 上加入 以便觀測資料變更,h3 tag 裡面加入 ngStyle
所以每當 click img 時會觸發 changeTitle() 讓 counter++ 連動 h3 字型大小
...
<img
(click)="changeTitle($event.altKey)"
[attr.data-title]="title"
[title]="title"
src="/assets/images/logo.png"
class="pull-left logo"
alt="The Will Will Web"
/>
...
<h3 [ngStyle]="{'font-size': 12 + counter + 'px'}">
記載著 Will 在網路世界的學習心得與技術分享 {{ counter }}
</h3>
範例二
寫入一個 return function
...
<img
(click)="changeTitle($event.altKey)"
[attr.data-title]="title"
[title]="title"
src="/assets/images/logo.png"
class="pull-left logo"
alt="The Will Will Web"
/>
...
<h3 [ngStyle]="getStyle()">
記載著 Will 在網路世界的學習心得與技術分享 {{ counter }}
</h3>
export class HeaderComponent implements OnInit {
title = "demo";
url = "http://blog.miniasp.com/";
counter = 0;
constructor() {}
changeTitle(altKey: boolean) {
if (altKey) {
this.title = "change title click";
}
this.counter++;
}
ngOnInit(): void {}
getStyle() {
return { "font-size": 12 + this.counter + "px" };
}
}
範例三
...
<img
(click)="changeTitle($event.altKey)"
[attr.data-title]="title"
[title]="title"
src="/assets/images/logo.png"
class="pull-left logo"
alt="The Will Will Web"
/>
...
<h3 [style.font-size]="(12 + counter) + 'px'" [style.color]="'red'">
記載著 Will 在網路世界的學習心得與技術分享 {{ counter }}
</h3>
NgClass
範例一
ngClass 後面綁定的值為 boolean,當 counter 餘數等於零時會加入 .highlight class
<h3 [ngClass]="{'highlight': counter % 2 == 0}">
記載著 Will 在網路世界的學習心得與技術分享 {{ counter }}
</h3>
.highlight {
background-color: coral;
}
範例二
<h3 [class.highlight]="counter % 2 == 0">
記載著 Will 在網路世界的學習心得與技術分享 {{ counter }}
</h3>
# 結構型指令
ngIf 的用法
當 2 餘數等於 0 時整個 DOM 會不見,餘數不等於 0 時就會出現,若 *ngIf 裡面放入 component directive 當消失在出現時資料會重新 Init (特別注意)
<div id="social-icons" class="pull-right social-icon" *ngIf="counter % 2 == 0 ">
...
</div>
ngSwitch
基本語法如下
[ngSwitch]="conditionExpression"
conditionExpression > 判斷式 *ngSwitchCase="expression" expression > 判斷式的值 *ngSwitchDefault > 預設的值
<div [ngSwitch]="conditionExpression">
<div *ngSwitchCase="expression">output</div>
<div *ngSwitchDefault>output2</div>
</div>
改一下 html 結構
判斷 counter % 2 若值等於 0, 1 顯示不同的 DOM,Default 顯示 NA
<div id="social-icons" class="pull-right social-icon">
<div [ngSwitch]="counter % 2">
<div *ngSwitchCase="0">
<a
href="https://plus.google.com/+WillHuang"
title="Will Huang (保哥) on Google+"
target="_blank"
>
<img src="/assets/images/googleplus.png" />
</a>
</div>
<div *ngSwitchCase="1">
<a
href="http://blog.miniasp.com/syndication.axd"
title="RSS 訂閱"
target="_blank"
>
<img src="/assets/images/rss.png" />
</a>
</div>
<div *ngSwitchDefault>NA</div>
</div>
</div>
但若 ngSwitch 使用 div 可能造成跑版問題,可以把 div 改成 ng-container ,在檢查時不會找到 div 這個 tag
<div id="social-icons" class="pull-right social-icon">
<ng-container [ngSwitch]="counter % 2">
<ng-container *ngSwitchCase="0">
<a
href="https://plus.google.com/+WillHuang"
title="Will Huang (保哥) on Google+"
target="_blank"
>
<img src="/assets/images/googleplus.png" />
</a>
</ng-container>
<ng-container *ngSwitchCase="1">
<a
href="http://blog.miniasp.com/syndication.axd"
title="RSS 訂閱"
target="_blank"
>
<img src="/assets/images/rss.png" />
</a>
</ng-container>
<ng-container *ngSwitchDefault>NA</ng-container>
</ng-container>
</div>
ngFor
使用 ngFor 跑文章的內容
先到 api 的資料夾複製 article.json 到 app.component.ts 裡面
app.component.ts
export class AppComponent {
keyword = "";
keywordReset() {
this.keyword = "";
}
data = [
{
id: 1,
href: "...",
title:
"...",
date: "2016/04/30 18:05",
author: "...",
category: "Visual Studio",
summary:
"<p>由於我只要用 <strong><font color='#ff0000' face='Consolas'>code .</font></strong>就可以快速啟動 Visual Studio Code 並自辦法。</p><p>... <a class='more' href='http://blog.miniasp.com/post/2016/04/30/Visual-Studio-Code-from-Command-Prompt-notes.aspx#continue'>繼續閱讀</a>...</p>",
},
...
];
}
把 article html 只留下一個其他的刪除,在 article tag 跑 ngFor 迴圈,再把資料帶進 html 裡面
app.component.html
<article
class="post"
id="post{{idx}}"
*ngFor="let item of data;let idx = index"
>
<header class="post-header">
<h2 class="post-title">
<!-- 一般用法 -->
<a [href]="item.href">{{ item.title }}</a>
</h2>
<div class="post-info clearfix">
<span class="post-date">
<i class="glyphicon glyphicon-calendar"></i>
{{ item.date }}
</span>
<span class="post-author">
<i class="glyphicon glyphicon-user"></i>
<a href="http://blog.miniasp.com/author/will.aspx">
{{ item.author }}
</a>
</span>
<span class="post-category">
<i class="glyphicon glyphicon-folder-close"></i>
<!-- 當變數有 '-' (category-link) 時需綁定 item['category-link'] -->
<a [href]="item['category-link']"> {{ item.category }} </a>
</span>
</div>
</header>
<!-- 當文章有 html tag 可以使用 innerHtml -->
<section class="post-body text" [innerHtml]="item.summary"></section>
</article>
innerHtml 就算內容加入 script 標籤也不用怕,Angular 會將 innerHtml 轉成字串以免受到 XSS 攻擊