Angular产生的档案实在太多辣,我们先专注在以下三个档案:
app.component.css
app.component.html
app.component.ts
xxx.spec.ts
是写测试时的档案,学习阶段时看到.spec.ts
都可以先忽略。
使用WebStorm IDE时,我个人会额外安装以下这两个套件
Component Folding 会让同一个元件的四个档案,以资料夹的形式(元件)来预览
CLI QuickSwitch 则是按下alt+S
时,在同一个元件内切换档案(.html
、.css
、.ts
)
什麽是范本、样板(template)? 就是 .html
档案
什麽是样式(style)? 就是 .css
档案
什麽是程序、元件(component)? 就是 .ts
档案
有时後元件指的是以上三个(样板、样式、程序)档案的集合体,
有时候是单纯指.ts
档案。
什麽是资料系结(binding)
?
资料系结就做一件事——绑定属性值。
其中又分成单向系结、双向系结
单向系结仅能从component把值传给template。
在绑定成功後,数值会传递过去、连动修改,
可以想像成是TS丢一个变数过去给HTML吃。
而双向系结则是两边都能连动、互传资料。
以下四种方法前三种都是单向系结,只有最後一项是双向系结。
{{property}}
把app.component.html
档案内容修改为以下
HTML
<div class="container my-5">
<h1>{{title}}</h1>
<a href="{{url}}">{{link}}</a>
</div>
当看到两个大括号{{}}
包住的值,
Angular会先对他们做解析(如果他不处理的话,HTML会看不懂这两个大括号在这干嘛用的)
并在app.component.ts
中设定属性变数
TS
...
export class AppComponent {
title = 'My Website';
link = '前往Google';
url = 'https://google.com';
}
也可以在程序部分额外加上callback函式,
在两秒後更换title文字,制造动态效果
TS
export class AppComponent {
title = 'My Website';
link = '前往Google';
url = 'https://google.com';
constructor() {
setTimeout(() => {
this.title = '我的网站';
}, 2000);
}
}
除了传递值,也可以在样板中直接做运算
HTML
<p>a+b: {{a + b}}</p>
TS
...
export class AppComponent {
a = 10;
b = 50;
}
[property] = 'statement'
HTML
<div class="container my-5">
<h1>标题</h1>
<a [href]="url">Google连结</a>
</div>
这次不用两个大括号了,当看到一个中括号[]
包住的属性(property),Angular会先对他们做解析(如果他不处理的话HTML也会看不懂这个中括号是在干嘛用的)
在HTML5里面,我们可以透过
data-
前缀开头的标签来自由定义扩充attribute。
但自定义的data-title
没办法透过属性系结来做绑定,因为h1 DOM底下没有这个property。不是所有有出现的attrubite都可以做属性绑定要如何查h1有哪些property?
在chrome浏览器中进入开发者模式检查
最右边这一大串,这些property都可以进行binding
那除了property以外,要如何绑定自定义的attribute呢?
内嵌系结
<h1 data-title={{title}}}>标题</h1>
也没办法使用解法:使用attr前缀来说明这是attribute属性
[attr.data-title]=title
回头来看,HTML确实吃到了自定义attribute
(event) = "method($event)"
(event) = "property=value"
此时加上一个button按钮,将HTML稍微修改一下。
HTML
<div class="container my-5">
<input type="button" value="更换标题">
<h1 [attr.data-title]=title>标题</h1>
</div>
我希望点击按钮之後才会更换网页大标题,可以透过Angular事件系结做到
可以用(click)="changeTitle()"
来绑定事件
HTML
<div class="container my-5">
<input type="button" value="更换标题" (click)="changeTitle()">
<h1>{{title}}</h1>
</div>
同时也在typesrcipt中加一个方法(method)
TS
export class AppComponent {
title = 'My Website';
changeTitle(){
this.title = '更换後的标题';
}
}
也有另一种比较不常用的做法 on-click="method()"
概念同JS的onclick事件做到
HTML
<input type="button" value="更换标题" on-click="changeTitle()">
$event
透过event参数可以做到更多样化的事
HTML
<div class="container my-5">
<input type="button" value="更换标题 (需同时按下Ctrl)" (click)="changeTitle($event)">
<h1>{{title}}</h1>
</div>
TS
export class AppComponent {
title = 'My Website';
changeTitle($event){
if ($event.ctrlKey){
this.title = '更换後的标题';
}
}
}
可标注传入参数的型别
标注为MouseEvent事件型别
changeTitle($event: MouseEvent){
if ($event.ctrlKey){
this.title = '更换後的标题';
}
}
也可修改如下:
HTML
(click)="changeTitle($event.ctrlKey)
TS
changeTitle(ctrlKey: boolean){
if (ctrlKey){
this.title = '更换後的标题';
}
}
[(ngModel)] = 'property'
双向系结能同时做到属性系结()
以及事件系结[]
,所以符号是[()]
用他来系结某个property
HTML
<div class="container">
<input type="text" value="" placeholder="请输入点什麽吧" [(ngModel)]="text">
<p>您的输入: <span>{{text}}</span></p>
<p>字数: <span>{{text.length}}</span></p>
</div>
TS
export class AppComponent {
text = '';
}
回到浏览器上一看,就出现错误讯息了 Can't bind to 'ngModel' since it isn't a known property of 'input'.
看一下IDE,有出现一个提示
Can't bind to [(ngModel)] since it is not provided by any applicable directives
回到 app.module.ts
中,import FomrsModule
就可以正常使用了
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
看到这里时就纳闷了,为何使用到
ngModel
还要去import一个不相干的form模组
?
原因是 NgModel
Creates a FormControl instance from a domain model and binds it to a form control element.
加上 按下ESC时清空输入框的效果
HTML
<div class="container">
<input type="text" value="" placeholder="请输入点什麽吧" [(ngModel)]="text" (keyup.escape)="textReset()">
<p>您的输入: <span>{{text}}</span></p>
<p>字数: <span>{{text.length}}</span></p>
</div>
TS
export class AppComponent {
text = '';
textReset(){
this.text = '';
}
}
与前面几种系结方式不同。
预设情况下,范本参考变数只能在样板中(.html
)使用
直接取得DOM物件,可以在当前的template中使用
变数名称不要与template property冲突
<div class="container">
<input type="text" value="" placeholder="请输入点什麽吧"
#tText
[(ngModel)]="text"
(keyup.escape)="textReset()">
<p>您的输入: <span>{{text}}</span></p>
<p>字数: <span>{{tText.value.length}}</span></p>
</div>
Directive 就是
<app-...>
就是直接套在别的component元件上、存取该元件底下的所有property
建立一个新的元件
> ng g c header
在该元件中写入一些HTML
<h1>Header!!</h1>
在app.component.html中加入该元件、引用进来
<div class="container">
<app-header #tHeader></app-header>
<input type="text" value="" placeholder="请输入点什麽吧"
#tText
[(ngModel)]="text"
(keyup.escape)="textReset()">
<p>您的输入: <span>{{text}}</span></p>
<p>字数: <span>{{tText.value.length}}</span></p>
<input type="button" value="更换标题" (click)="tHeader.title = '更改过後的标题'">
</div>
<<: Day28 softirq, tasklet, workqueue
>>: [Day28] 测试依赖外层 Context Provider 的 React 元件:客制化 render 函式
最後来看Native 端(iOS): 补充:iOS 中的 .h 和.m 档 .h 为标头档,做为宣告...
前言 昨天已经将 addAlarmTableViewCell 在 addAlarmTableView...
所有雇员(All employees) 总体上,“所有员工”是接受或参加意识介绍或活动的理想目标,...
开发一个系统最无聊的过程大概就是除错了,尤其是那种尝试对 null 物件取值的错误(Object r...
疫情爆发,改变很多人的购物习惯,大多数的人买东西,尤其是高贵的3C产品,都会上网比价,再怎样都不能买...