一、NgModule
被@NgModule所装饰的类被称为angular module
@NgModule元数据
- declarations —— 该模块的依赖项(该模块用到的组件、指令、管道)。
- imports —— 导入其他的ngModule。
- providers —— 提供各种服务。
- bootstrap —— 根组件,Angular 创建它并插入 index.html 宿主页面
declarations 数组
1.模块中使用的组件必须先在declarations 数组中声名
2.一个组件只能被一个模块声名
3.在declarations中的组件默认只能在当前模块中使用,在其他模块使用必须exports导出
imports 数组
1.只会出现在@NgModule装饰器中。
2.模块想要正常工作,除了本身的依赖项(declarations),还可能需要其他模块导出的依赖项。
3.只要是angular module,都可以导入imports数组中,比如ng内置、第三方、自定义的模块。
providers 数组
该数组为当前模块提供一系列服务
bootstrap 数组
应用是通过引导根模块 AppModule 来启动的,引导过程还会创建 bootstrap 数组中列出的组件,并把它们逐个插入到浏览器的 DOM 中。
该数组中的每个组件,都作为组件树的根(根组件),后续所有组件都是基于根组件的(如图)。
虽然也可以在宿主页面中放多个组件,但是大多数应用只有一个组件树,并且只从一个根组件开始引导。
这个根组件通常叫做 AppComponent,并且位于根模块的 bootstrap 数组中。
结构图
二、模板基础语法
1. 模板表达式
模版中还可以写些简单的逻辑,比如判断或运算
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `<h1>{{title}}</h1>
<p> sum : {{1 + 1}}</p>
<p>price: {{price * 0.7}}</p>
<p>与方法结合: {{price * 0.7 + getVal()}}.</p>
`, //内联模板
styles: [`h1 { color: yellow }`] //内联样式
})
export class AppComponent {
title = 'my-angular-title';
price = 30
getVal(): number {
return 33;
}
}
模板表达式遵循原则:
-
非常简单
-
执行迅速
-
没有可见的副作用(即模版中的逻辑不能改变组件的变量)
2. 模板来源
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] //注意: styleUrls
})
export class AppComponent {
}
3. 属性绑定
<img src="../assets/images/zorro.jpg" alt="madao" /><!-- 静态绑定-->
<img [src]="zorroSrc" alt="zorro" /> <!-- 简写形式-->
<img bind-src="zorroSrc" alt="zorro" /> <!-- 完整形式-->
<button [disabled]="isDisabled">click</button>
<!-- zorroSrc、zorro、isDisabled均为变量 -->
4. 自定义属性绑定
<p [attr.data-title]="customTitle">一行文字</p>
<p [attr.title]="customTitle">测试自定义标题属性</p>
5. 插值表达式属性绑定
<img src="{{ picUrl }}" alt="{{ picInfo }}" /> <!-- 不常用 -->
6. 单个class样式绑定
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<button type="button" class="btn" [class.btn-primary]="theme === 'primary'">Primary</button>
<button type="button" class="btn" [class.btn-secondary]="true">secondary</button>
<button type="button" class="btn" [class.btn-success]="isSuccess">success</button>
<button type="button" class="btn" [class.btn-danger]="'啦啦啦'">danger</button>
<button type="button" class="btn" [class.btn-danger]="0">danger</button>
<button type="button" class="btn" [class.btn-danger]="undefined">danger</button>
`,
styles: []
})
export class AppComponent {
theme = 'primary';
isSuccess = true;
}
7. 绑定多个class
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<button type="button" [class]="btnCls">btnCls</button>
<button type="button" [class]="btnCls2">btnCls2</button>
<button type="button" [class]="btnCls3">btnCls3</button>
<!-- 也可以用内置指令ngClass -->
<button type="button" [ngClass]="btnCls">btnCls</button>
<button type="button" [ngClass]="btnCls2">btnCls2</button>
<button type="button" [ngClass]="btnCls3">btnCls3</button>
`,
styles: []
})
export class AppComponent {
btnCls = 'btn btn-primary';
btnCls2 = ['btn', 'btn-success'];
btnCls3 = {
btn: true,
'btn-info': true
};
}
8. 绑定单个style
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<p [style.color]="'#f60'">一段文字</p>
<p [style.height]="'50px'" [style.border]="'1px solid'">设置高度</p>
<p [style.height.px]="50" [style.border]="'1px solid'">设置高度</p>
`,
styles: []
})
export class AppComponent {}
9. 绑定多个style
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<p [style]="style1">style1</p>
<p [style]="style2">style2</p>
<p [style]="style3">style3</p>
<!-- 内置指令ngStyle绑定, 不推荐 -->
<!-- <p [ngStyle]="style1">style1</p>-->
<!-- <p [ngStyle]="style2">style2</p>-->
<!-- ngStyle只接收对象 -->
<p [ngStyle]="style3">style3</p>
`,
styles: []
})
export class AppComponent {
style1 = 'width: 200px;height: 50px;text-align: center;border: 1px solid;';
style2 = ['width', '200px', 'height', '50px', 'text-align', 'center', 'border', '1px solid']; // 有问题
style3 = {
width: '200px',
height: '50px',
'text-align': 'center',
border: '1px solid'
};
样式优先级
1.某个类或样式绑定越具体,它的优先级就越高
2.绑定总是优先于静态属性
10. 绑定事件
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<button (click)="onClick()">CLICK</button>
<button (click)="onClick1($event)">Primary</button>
`,
styles: []
})
export class AppComponent {
onClick() {
console.log('onClick');
}
onClick1(event: MouseEvent) {
console.log('onClick1', event.target);
}
}
11. 输入与输出属性
输入属性:用于父组件传值给子组件(父传子)
@Input()输出属性:用于子组件传值给父组件(子传父)
@Output()
输入属性@Input
♏父组件♏
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-mycpn [item]="currentItem"></app-mycpn>
<!-- <app-mycpn item="我是传入的字符串"></app-mycpn>--> <!--静态属性可不用[]包裹 -->
`,
})
export class AppComponent {
currentItem = 'Television';
}
♏子组件♏
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-mycpn',
template: `<p>
Today's item: {{item}}
</p>`
})
export class MycpnComponent {
@Input() item: string;
//@Input('aliasItem') item: string; 提供别名,item变量只可以在本组件使用
//相当于对父组件传入的aliasItem变量进行重命名
}
输出属性@Output()
♏父组件♏
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-mycpn (newItemEvent)="addItem($event)"></app-mycpn>
`,
})
export class AppComponent {
items = ['item1', 'item2', 'item3', 'item4'];
addItem(newItem: string) {
this.items.push(newItem);
}
}
♏子组件♏
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-mycpn',
template: `<label>Add an item: <input #newItem></label>
<button (click)="addNewItem(newItem.value)">Add to parent's list</button>`
})
export class MycpnComponent {
@Output() newItemEvent = new EventEmitter<string>();
// @Output('newItem') newItemEvent = new EventEmitter<string>();
addNewItem(value: string) {
this.newItemEvent.emit(value);
}
}
还可以元数据中声名输入、输出属性。(不推荐)
三、组件样式
宿主选择器
:host选择是是把宿主元素作为目标的唯一方式
它选中的是组件模板标签,比如<app-child></app-child>,
相当于在父组件的style中使用标签选择器选择 app-child {}
当宿主标签上有类名 active时生效
:host(.active) {
border-width: 3px solid #ccc;
}
祖先选择器
当某个祖先元素有 CSS 类 light 时,才会把 background-color 样式应用到组件内部的所有 .title 元素中,找到根元素(html标签)为止
:host-context(.light) .title {
background-color: #bfa;
}
样式模块化
在
@Component的元数据中指定的样式只会对该组件的模板生效组件的样式不会影响到子组件中的模板
组件的样式不会影响到投影内容
视图封装模式
ShadowDom -- 不进不出,没有样式能进来,组件样式出不去, 就自己玩
Emulated --只进不出, 默认选项,全局样式能进来,组件样式出不去
None -- 能进能出,此时组件的样式是全局生效的,注意与其他组件发生样式冲突,
(对父组件样式也能生效)