Angular教程 240103
感谢大地。
快捷键
1 代码整理快捷键:
mac : ↑ + option +f
wind: shift alt f
2 windows 繁体字 繁简转换快捷键
: control+shift +f
3 侧边栏的“资源管理器”没有了,怎么也找不到,邮件也没有找到。
快捷键 Ctrl+Shift+P
或者:
选择“查看view 表示 ”下的“命令面板Command Palette コマンド パレット”
-View
- Command Palette
输入:View: Reset View Locations
ビユーの位置をリセットする
所有的视图会恢复到默认的位置
4
01 Angular介绍、安装Angular Cli、创建Angular项目 预编译器Scss Less css配置
02 Angular目录结构分析、app.module.ts详解、以及Angular中创建组件、组件详解、 绑定数据
1. Angular 目录结构分析
1根目录
- /e2e/: 端到端的测试文件 (End-to-End) 位于这个文件夹。
- /node_modules/: 存放所有的npm依赖包。
2/src 目录
- /app/: 包含所有的业务逻辑和视图控制代码,是构建app的核心文件。
- app.module.ts: 根模块文件。
- /environments/: 包含不同环境的配置文件。
- favicon.ico: 网站的图标。
- index.html: 主页面。
- main.ts: Angular的主入口文件。
- polyfills.ts: 浏览器兼容性补丁 (polyfill) 文件。
- styles.css: 应用的全局样式文件。
- test.ts: 单元测试入口文件。
3根目录文件
- .angular-cli.json: Angular CLI的配置文件。
- .editorconfig: 编辑器配置,保持代码风格一致性。
- .gitignore: Git的忽略配置文件。
- karma.conf.js: Karma的单元测试配置文件。
- package.json: 定义项目依赖和npm命令。
- protractor.conf.js: Protractor的端到端测试配置文件。
- README.md: 项目的README文件。
- tsconfig.json: TypeScript编译器配置文件。
- tslint.json: TSLint的代码质量检查配置文件。
4版本2参照
/src 目录: 这是项目的主要目录,包含应用程序的所有源代码。
app 文件夹: 包含应用程序的核心文件,如模块、组件、服务和管道。
components: 存放自定义组件。
services: 存放服务文件,用于业务逻辑和数据管理。
models: 定义数据模型。
assets: 存放静态资源,如图片、样式表和JSON文件。
environments: 包含不同环境的配置文件,如开发和生产环境。
/node_modules 目录: 存放所有的npm依赖包。
/e2e 目录: 存放端到端测试文件。
根目录文件:
angular.json: Angular CLI的配置文件。
package.json 和 package-lock.json: 定义项目依赖和锁定版本。
tsconfig.json: TypeScript编译器的配置文件。
/dist 目录: 存放构建后的文件,用于部署。
Angular的这种目录结构有利于团队合作和项目的可扩展性。每个部分都有明确的职责,使得开发者可以快速定位和更新代码。这种结构也方便了测试和部署。
5app.module.ts文件
定义 AppModule,这个根模块会告诉 Angular 如何组装该应用。
/*这个文件是Angular 根模块,告诉Angular如何组装应用*/
//BrowserModule,浏览器解析的模块
import { BrowserModule } from '@angular/platform-browser';
//Angular核心模块
import { NgModule } from '@angular/core';
//根组件
import { AppComponent } from './app.component';
//使用命令 ng g component components/news 也是自动引入 并声明配置在 declarations 项目运行所需要的组建中去
import { NewsComponent } from './components/news/news.component';
import { HomeComponent } from './components/home/home.component';
import { HeaderComponent } from './components/header/header.component';
/*@NgModule装饰器, @NgModule接受一个元数据对象,告诉 Angular 如何编译和启动应用*/
@NgModule({
declarations: [ /*配置当前项目运行的的组件*/
AppComponent,
NewsComponent,
HomeComponent,
HeaderComponent
],
imports: [ /*配置当前模块运行依赖的其他模块*/
BrowserModule
],
providers: [], /*配置项目所需要的服务*/
bootstrap: [AppComponent] /* 指定应用的主视图(称为根组件) 通过引导根AppModule来启动应用 ,这里一般写的是根组件*/
})
//表示暴露根模块 ,但根模块不需要导出任何东西, 因为其它组件不需要导入根模块
export class AppModule { }
6自定义组件
创建组件
ng g component components/header
ng g component components/news
组件内容详解:
import { Component,OnInit }from '@angular/core';
//*引入 angular 核心
@Component({
selector:'app-header', //*使用这个组件的名称
templateUrl:'./header.component.html',//*html 模板
styleUrls: ['./header.component.css'] //*css 样式
})
//export暴露整个组件
export class HeaderComponent implements OnInit {//*实现接口
title='my-app'; //定义属性
constructor(){//*构造函数
}
ngOnInt() [] //*初始化加载的生命周期函数
}
- 绑定数据
定义数据
绑定数据
Angular 中使用{{}}绑定业务逻辑里面定义的数据
03 Angular创建组件 声明属性的几种方式、ts定义属性、绑定数据、绑定属性、绑定html、数据循环、循环多维数组
1. Angular 组件、数据绑定和数据循环
1.1 创建 angualr 组件
ng g component components/news
1
使用组件:
1.2 属性–Angular数据绑定
TS文件初始化数据,html文件绑定数据
1 定义属性数据
import { Component } from '@angular/core';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent {
title = "--ts 我是一个新闻组件的属性";//后台定义的属性,要绑定到前台来使用
// public title = "我是一个新闻组件的属性"; 完整版 是要声明属性的公开程度
public username: string = "zyy";
}
2 绑定属性数据
<h3>我是一个新闻组件 </h3>
<app-header></app-header>
{{title}}
<!-- 通过花括号可以将后台定义的属性,绑定到前台 -->
<div> {{username}}
</div>
<hr>
3 声明属性的几种方式:
public 共有 *(默认) 可以在这个类里面使用、也可以在类外面使用
protected 保护类型 他只有在当前类和它的子类里面可以访问
private 私有 只有在当前类才可以访问这个属性
1.3 对象–Angular数据绑定
1 定义一个对象
public userinfo: any = {
username: 'wdm',
age: 33
}
public msg: string = '我是msg';
2 绑定对象数据
{{userinfo.username}}
{{userinfo.age}}
1.4 oninit angular 中 自己引入生命周期钩子
1 整个生命周期钩子地图 及OnInit的位置
import { Component, Input, OnInit, OnChanges, OnDestroy, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked } from '@angular/core';
@Component({
selector: 'app-example',
template: '<ng-content></ng-content>',
// 这里用ng-content投射内容
})
export class ExampleComponent implements OnInit, OnChanges, OnDestroy, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked {
@Input() data: any; // 绑定的属性
constructor() { }
ngOnChanges() {
// 当@Input绑定的属性发生变动时调用
}
ngOnInit() {
// 在组件初始化时调用
}
ngDoCheck() {
// 在每次变更检测运行期间调用
}
ngAfterContentInit() {
// 在内容(或ng-content)投射到视图时调用
}
ngAfterContentChecked() {
// 每次投射的内容发生改变时调用
}
ngAfterViewInit() {
// 在组件(和子组件)初始化完成时调用
}
ngAfterViewChecked() {
// 每次组件(和子组件)视图被检测时调用
}
ngOnDestroy() {
// 在组件销毁时调用
}
}
2 import oninit如何操作
在 Angular 中,当你使用 Angular CLI 来生成一个新的组件时,默认情况下 OnInit 生命周期钩子并不会自动被引入或实现。你需要手动添加这些部分。
OnInit 是一个 Angular 生命周期钩子,用于在组件初始化时执行代码。这意味着当你的组件准备好显示或与之交互时,Angular 会调用 ngOnInit() 方法。
在 Angular 中,如果你想在你的组件中使用 OnInit 生命周期钩子,你需要遵循以下步骤:
1 引入 OnInit:
首先,你需要从 @angular/core 包中引入 OnInit。这是通过使用 import 语句完成的。
2 实现 OnInit 接口:
在你的组件类中实现 OnInit 接口。这意味着你的[组件类]将包含一个特定的方法 ngOnInit(),Angular 会在初始化组件时调用这个方法。
3 定义 ngOnInit() 方法:
在你的组件类中定义 ngOnInit() 方法。在这个方法内部,你可以放置初始化组件所需的逻辑。
以下是一个简单的例子:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnInit {
constructor() { }
ngOnInit(): void {
// 在这里编写初始化逻辑
}
}
<!--我们从 @angular/core 导入了 Component 和 OnInit。
我们创建了一个名为 MyComponent 的新组件。
我们通过实现 OnInit 接口表明这个组件将使用 OnInit 生命周期钩子。
在 ngOnInit() 方法中,我们可以添加初始化组件时需要执行的代码。-->
3 OnInit初始化设置的常用方法
一些常用的 ngOnInit 方法
ngOnInit 是 Angular 生命周期钩子中的一个重要方法,通常用于在组件初始化完成后执行一些初始化工作。下面是一些常用的 ngOnInit 方法示例:
1发起HTTP请求并获取数据:
ngOnInit(): void {
this.userService.getUserData().subscribe(data => {
this.userData = data;
});
}
2初始化一些组件属性:
ngOnInit(): void {
this.title = "Welcome to My App";
this.subtitle = "Angular is awesome!";
}
3订阅一些服务或事件:
ngOnInit(): void {
this.authService.userLoggedIn.subscribe(isLoggedIn => {
this.isUserLoggedIn = isLoggedIn;
});
}
4执行一些其他初始化操作:
ngOnInit(): void {
// 执行一些其他初始化操作
this.initializeSomething();
}
在组件
5`初始化时执行特定逻辑:
ngOnInit(): void {
if (this.isSpecialComponent) {
this.specialComponentInit();
}
}
这些示例展示了 ngOnInit 可能用于的不同情况,可以根据你的组件需求在 ngOnInit 中执行适当的初始化工作。
4 简单的完整例子
让我们通过一个简单的例子来解释这个概念。假设我们有一个组件,它显示一段欢迎消息。我们将在 ngOnInit() 方法中设置这个消息。
4-1 news.component组件
1 ts文件。
- news.component.ts
import { Component } from '@angular/core';
import { OnInit } from '@angular/core';
import { Userinfo } from './userinfo';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
// 第一种:直接在构造函数中 进行生命周期设置的初始化赋值
//第二种 :在ngOnInit中进行 初始化设置
constructor() { }
welcomeMessage!: String;//定义一个属性
userinfo: Userinfo = new Userinfo("", 0); // 使用默认值
// 或着: userinfo!: Userinfo; //
ngOnInit(): void {
// 在 ngOnInit 中执行初始化逻辑
// 1 初始化 属性 赋值
this.welcomeMessage = '欢迎来到俺的 Angular 应用!';
console.log(this.welcomeMessage);
alert(this.welcomeMessage);
//--------------
//2 初始化 特定的逻辑
this.userinfo = new Userinfo("Alice", 30);
}
}
- 其中userinfo.ts
/**。首先,你定义了 class Userinfo 在 NewsComponent 内部,但 TypeScript 不允许在类内部直接定义其他类。需要将 Userinfo 类移出 NewsComponent 类。
另外,为了能够正确地在 NewsComponent 中使用 Userinfo 类,需要确保 Userinfo 类的定义位于 NewsComponent 类之前,或者将它提取到一个单独的 TypeScript 文件中,并在需要的地方引入它。
以下是修复后的代码:
首先,将 Userinfo 类定义提取到一个单独的 TypeScript 文件,例如 userinfo.ts。
在 NewsComponent 中引入 Userinfo 类,并使用它。
*/
export class Userinfo {
// 在这里定义构造函数、属性、方法等
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 还可以定义其他属性和方法
name: string;
age: number;
getInfo() {
return `Name: ${this.name}, Age: ${this.age}`;
}
}
2 html文件
<h3>我是一个新闻组件 </h3>
<app-header></app-header>
<h3> </h3>
{{welcomeMessage}}
<br/>
{{userinfo.name}}
{{userinfo.age}}
<br/>
4-2显示消息在 news.component.html:
打开 news.component.html 文件,并添加以下代码来显示欢迎消息:
html
{{ welcomeMessage }}
这个例子中的 ngOnInit() 方法在组件初始化时被调用,并设置 welcomeMessage 属性。然后,这个消息在组件的 HTML 模板中通过插值表达式 {{ welcomeMessage }} 显示出来。当你运行你的 Angular 应用并导航到这个组件时,你将看到显示了 “欢迎来到我的 Angular 应用!” 的消息。这就是 OnInit 的基本用法,它对于设置初始数据和执行启动时的逻辑非常有用。
4-3构造函数和 生命周期钩子 进行初始化 有什么区别?
constructor() {
}
ngOnInit() { } 进行初始化 有什么区别?
区别在于时机和用途:
- constructor 在对象创建时立即调用,用于基本设置和依赖注入。
- ngOnInit 在组件初始化阶段被调用,用于执行与组件模板和视图相关的初始化操作。
- 在大多数情况下,应该将组件的初始化逻辑放在 ngOnInit 中,以确保在组件完全准备好时执行。如果只是进行一些基本的设置和依赖注入,可以使用 constructor。但避免在 constructor 中执行可能导致异步问题的操作,因为 Angular 在 ngOnInit 阶段提供了更安全的初始化时机。
4-4 常见初始化报错:
Property ‘userinfo’ has no initializer and is not definitely assigned in the constructor.ts(2564)
(property) NewsComponent.userinfo: Userinfo
属性’userinfo’没有初始化器,并且在构造函数中没有被确定赋值.ts(2564)
(property) NewsComponent.userinfo: 用户信息
这个错误是 TypeScript 中的一个编译器警告,它表示 userinfo 属性没有在构造函数中初始化并且没有被标记为可以为 null 或 undefined 的情况。为了解决这个问题,可以采取以下几种方法之一:
- 1给 userinfo 属性一个初始值:
userinfo: Userinfo = new Userinfo("", 0); // 使用默认值
这样,在构造函数中不再需要初始化 userinfo,因为它已经在属性声明时被初始化了。
- 2 在 tsconfig.json 中启用 strictPropertyInitialization 选项(TypeScript 2.7+),这将强制要求你在构造函数中初始化类属性,或者通过属性声明时分配一个初始值。这可以提高代码的类型安全性。
{
"compilerOptions": {
"strictPropertyInitialization": true
}
}
- 3 如果你确定 userinfo 属性在 ngOnInit 中会被正确初始化,可以使用非空断言操作符 !:
userinfo!: Userinfo;
非空断言操作符 ! 的主要作用是告诉 TypeScript 编译器,在你的代码逻辑中,
你确信某个属性或变量一定会在运行时被赋值,不会为空或未定义。
如果你在代码中省略了 !,那么 TypeScript 将进行严格的空值检查,
如果存在潜在的空值情况,会发出编译时的警告或错误。
并要求你在使用变量或属性之前进行空值检查或确保其值不为空。
这是 TypeScript 的一种类型安全机制,旨在防止潜在的空值错误,提高代码的健壮性。
因此,与userinfo: Userinfo;相比,userinfo!: Userinfo;
这将告诉 TypeScript 编译器,虽然没有在构造函数中初始化 userinfo,但在 ngOnInit 中会被正确初始化,因此可以放心地使用它。不过要确保在 ngOnInit 中确实对 userinfo 进行了初始化,以避免运行时错误。
选择哪种方法取决于的需求和设计,但在实际开发中,最好在构造函数中或属性声明时进行属性的初始化,以确保代码的可维护性和类型安全性。
1.5 绑定属性
1.html
<br/>
<h3>angular绑定属性:
</h3>
<div title="我是div angular绑定属性">鼠标瞄上来看一下 </div>
1.6 angular还支持简单的计算
<h1>angular还支持简单的计算</h1>
<h2>1+2={{1+2}}</h2>
运行结果:
1.7 数据循环 *ngFor
1.4.1 示例01:
这两种定义数组的方式都是相当nice的。
// public arrs: string[] = [‘一’, ‘二’, ‘三’, ‘四’, ‘五’]; // 推荐写法
public arrs: Array = [‘一’, ‘二’, ‘三’, ‘四’, ‘五’];
1
2
<li *ngFor=“let arr of arrs”>
{{arr}}
1.4.2 示例02:
public userlist:any[]=[{
username:‘张三’,
age:20
},{
username:‘李四’,
age:21
},
{
username:‘王五’,
age:40
}];
<ul>
<li *ngFor="let item of userlist">
{{item.username}}-------{{item.age}}
</li>
</ul>
1.4.3 示例03:
public cars: any[] = [
{
cate: ‘宝马’,
list: [
{
title: ‘宝马x1’,
price: ‘30万’,
},
{
title: ‘宝马x2’,
price: ‘30万’,
},
{
title: ‘宝马x3’,
price: ‘40万’,
},
],
},
{
cate: ‘奥迪’,
list: [
{
title: ‘奥迪q1’,
price: ‘40万’,
},
{
title: ‘奥迪q2’,
price: ‘40万’,
},
{
title: ‘奥迪q3’,
price: ‘30万’,
},
],
},
];
<ul>
<li *ngFor="let item of cars">
<b>{{item.cate}}</b>
<ol>
<li *ngFor="let car of item.list">
<i>{{car.title}}</i>-----<i>{{car.price}}</i>
</li>
</ol>
</li>
</ul>
1.4.4 循环数据:显示索引
public list: any[] = [
{ title: ‘我是新闻01’ },
{ title: ‘我是新闻02’ },
{ title: ‘我是新闻03’ },
{ title: ‘我是新闻04’ },
{ title: ‘我是新闻05’ },
];