Skip to content

angular 文档

作者:Yuan Tang
更新于:5 个月前
字数统计:5.9k 字
阅读时长:20 分钟
image-20230410111628117
  1. ViewChild:属性装饰器,通过它可以获得视图上对应的元素;
  2. ViewContainerRef:视图容器,可在其上创建、删除组件;
  3. ComponentFactoryResolver:组件解析器,可以将一个组件呈现在另一个组件的视图上。

cli命令

ng serve -o(open)

ng g component xzy 新建一个xzy组件 包括ts html css文件

目前angular不支持使用cli命令删除创建的组件你需要手动删除相关

ng generate 官网文档选项

组件ts文件

image-20230423135137697

定义组件模板两种方式

@Component({
  selector: 'app-component-overview',
  templateUrl: './component-overview.component.html',
})
或者用template
@Component({
  selector: 'app-component-overview',
  template: '<h1>Hello World!</h1>',
})

Angular 组件需要一个用 templatetemplateUrl 定义的模板。但你不能在组件中同时拥有这两个语句。

声明组件的样式

和定义组件模板类似

@Component({
 styleUrls: ['./componentoverview.component.css']或者
  styles: ['h1 { font-weight: normal; }']
})

你也可以将styleUrls的css文件改为sass 活less文件

ag生命周期

当 Angular 实例化组件类并渲染组件视图及其子视图时,组件实例的生命周期就开始了。生命周期一直伴随着变更检测,Angular 会检查数据绑定属性何时发生变化,并按需更新视图和组件实例。当 Angular 销毁组件实例并从 DOM 中移除它渲染的模板时,生命周期就结束了。当 Angular 在执行过程中创建、更新和销毁实例时,指令就有了类似的生命周期。

每个接口都有唯一的一个钩子方法,它们的名字是由接口名再加上 ng 前缀构成的。比如,OnInit 接口的钩子方法叫做 ngOnInit()。如果你在组件或指令类中实现了这个方法,Angular 就会在首次检查完组件或指令的输入属性后,紧接着调用它。

image-20230423141010638image-20230423141024048image-20230423141049629

ngAfterViewInit() -->mounted()

语法

插值语法
<h2>{{hero.name | uppercase}} Details</h2>
//你也可以自定义管道符
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'myCustomPipe' })
export class MyCustomPipe implements PipeTransform {
  transform(value: string): string {
    // 进行转换操作
    return value.toUpperCase(); // 示例:将字符串转为大写字母
  }
}

管道符

angular内置的一些管道

AsyncPipe:用于在模板中处理异步数据。
UpperCasePipe:将字符串转换为大写形式。
LowerCasePipe:将字符串转换为小写形式。
DatePipe:用于格式化日期。
DecimalPipe:用于格式化数字。
CurrencyPipe:用于格式化货币值。
PercentPipe:用于格式化百分比值。

类绑定

[class.selected]="hero === selectedHero"
"hero === selectedHero"根据这个条件判断是否添加selected css

Angular 只会绑定到组件的公共属性。

@Component

@Component 是个装饰器函数,用于为该组件指定 Angular 所需的元数据。

元数据::
selector:组件的选择器,用来在模板中标识组件。
templateUrl:组件的模板文件的路径,用来定义组件的视图。
styleUrls:组件的样式文件的路径,用来定义组件的外观。
inputs:组件的输入属性,用来从外部接收数据。
outputs:组件的输出属性,用来向外部发送事件。
providers:组件的依赖注入提供者,用来定义组件所需的服务或令牌。
viewProviders:组件的视图依赖注入提供者,用来定义组件视图所需的服务或令牌。
changeDetection:组件的变更检测策略,用来优化性能。
encapsulation:组件的样式封装模式,用来控制样式的作用域。
preserveWhitespaces:组件的空白保留选项,用来控制模板中的空白字符。

如果要更改默认的 styleUrls 后缀为 .less,需要在 Angular 的配置文件 angular.json 中进行修改。例如:

"projects": {
  "your-project-name": {
    "schematics": {
      "@schematics/angular:component": {
        "styleext": "less"
      }
    }
  }
}

你也可以使用 命令ng config schematics.@schematics/angular:component.styleext less

@Input() 父传子

@Input
Component本身是一种支持 nest 的结构,Child和Parent之间,如果Parent需要把数据传输给child并在child自己的页面中显示,则需要在Child的对应 directive 标示为 input。  
@Input() name: string;

@Input还可以使用typescript的get set存取器的方式来设置属性

text
private _name: string;

@Input get name() {return this._name;}
set(name:string) {this._name = name;}

@Output 子传父

input 事件:在 input 元素值发生改变时触发,不包括文本框失去焦点的情况;
change 事件:在 input 元素失去焦点且元素的值已经发生变化时触发;
blur 事件:在 input 元素失去焦点时触发,不管元素的值有没有发生变化。

子组件ts文件定义  @Output() onInputChange = new EventEmitter<string>();  this.onInputChange.emit(inputValue); 父组件通过(onInputChange)="handleInputChange($event)去触发

@Injectable()服务

Routing路由

image-20230424151154676
import { routes } from './components/routes'
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { } 
//routes是路由具体配置
image-20230424161620275
  <a routerLink="/heroes">Heroes</a> 点击跳转路由
  <router-outlet></router-outlet> 会告诉路由器要在哪里显示路由的视图。
image-20230425162025505
默认路由以及重定向
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },

根据id值详情导航

image-20230424164206514
import { ActivatedRoute } from '@angular/router';
ActivatedRoute保存着到这个 HeroDetailComponent 实例的路由信息。这个组件对从 URL 中提取的路由参数感兴趣。其中的 id 参数就是要显示的英雄的 id。

RxJS 库Observable 和of

理解不深刻需要进行研究

getHero(id: number): Observable<Hero> {

  const hero = HEROES.find(h => h.id === id)!;
  this.messageService.add(`HeroService: fetched hero id=${id}`);
  return of(hero);
}


Observable 是 RxJS 库中的一个对象,它代表一个可观察的数据流。Observable 可以用来处理异步数据流,例如从服务器获取数据或用户输入等。它可以发出多个值并且在发出值时允许你执行一些操作,例如过滤、转换和组合等。你可以订阅 Observable,以便在数据流中有新值可用时收到通知。
of 是 RxJS 库中的一个操作符,它用于创建一个新的 Observable 对象,该对象会发出指定的值,然后立即完成。例如,of(1, 2, 3) 将创建一个 Observable,它会发出值 1, 2, 3,然后立即完成。of 可以用来创建一个 Observable,这个 Observable 可以在不需要异步操作的情况下返回一些值。

在上述代码中,of 用于创建一个 Observable 对象,它发出了从 HEROES 数组中找到的英雄对象,并且在数据流中立即完成。这样做是因为这个例子中的数据是静态的,不需要从服务器异步获取,所以我们可以使用 of 创建一个 Observable,以返回这个英雄对象。

启用 HTTP 服务 HttpClient

HttpClient 是 Angular 通过 HTTP 与远程服务器通讯的机制。

vuex和HttpClient对比

HttpClient 是 Angular 框架提供的一个 HTTP 客户端,用于与服务器进行 HTTP 通信,它主要用于获取和发送数据。

Vuex 是 Vue.js 的一个状态管理库,它提供了一种集中式存储管理应用所有组件的状态的方案,使得组件之间可以共享状态,方便组件的协同工作。

虽然它们都提供了一种在应用程序中共享数据的方式,但 HttpClient 更多的是用于实现数据的获取和发送,而 Vuex 则更注重状态的管理和共享。在 Angular 中,如果你需要共享数据或状态,则可以使用 Angular 的服务或 RxJS 的 Subject 或 BehaviorSubject 等数据流处理工具。

以下是一些 Angular 中的术语和 Vue 中类似的术语和概念:

Angular 的组件 (Component) 和 Vue 的组件 (Component) 相似,都是将页面拆分成独立的可重用部分。Angular 的组件使用类来定义,包含 HTML 模板、样式和逻辑。
Angular 的指令 (Directive) 和 Vue 的指令 (Directive) 相似,都是可以在 HTML 元素上添加特殊的行为和样式。Angular 的指令包含三种类型:组件指令、结构型指令和属性型指令。
Angular 的服务 (Service) 和 Vue 的插件 (Plugin) 相似,都是提供全局可用的功能模块。Angular 的服务用于封装数据和业务逻辑,可以被组件和其他服务注入和使用。
Angular 的模块 (Module) 和 Vue 的模块 (Module) 相似,都是将应用程序拆分成功能模块。Angular 的模块用于声明组件、指令、管道和服务,并导入其他模块。
Angular 的路由 (Router) 和 Vue 的路由 (Router) 相似,都是用于实现单页应用程序的导航和页面跳转。Angular 的路由使用配置文件来定义路由,可以懒加载组件。
Angular 的表单 (Form) 和 Vue 的表单 (Form) 相似,都是用于处理用户输入和数据校验。Angular 的表单提供模板驱动表单和响应式表单两种形式,支持多种验证器。
image-20230426172039701

表单触发的类名

  • ng-submit

提交表单后,Angular 会将 ng-submitted 类应用于 form 元素。此类可用于在提交后更改表单的样式。

image-20230427155839118

理解angular

{ path: '', redirectTo: '/dashboard', pathMatch: 'prefix' },

 这段代码的步骤解释如下: 
1.  path: ''  表示根路径。 
2.  redirectTo: '/dashboard'  表示将根路径重定向到 '/dashboard'。 
3.  pathMatch: 'full'  表示只有当路径完全匹配时才进行重定向。 
 所以,这段代码的意思是如果用户访问根路径,会被自动重定向到 '/dashboard'。

pathMatch: 'prefix'pathMatch: 'full' 是Angular路由配置中的两个不同的选项,用于指定路径匹配的方式。

  • pathMatch: 'prefix' 表示路径匹配的前缀模式。当使用此选项时,如果URL的路径以配置的路径开头,则认为匹配成功。例如,如果配置了 path: 'dashboard' ,则URL路径为 '/dashboard/home' 或 '/dashboard/settings' 都会与该配置匹配。
  • pathMatch: 'full' 表示路径匹配的完全模式。当使用此选项时,URL的路径必须与配置的路径完全相同才会认为匹配成功。例如,如果配置了 path: 'dashboard' ,则URL路径必须为 '/dashboard' 才会与该配置匹配。 总结起来, pathMatch: 'prefix' 匹配路径的前缀,而 pathMatch: 'full' 则要求路径完全相同。

视图封装

image-20230705142950961
ViewEncapsulation.None 可以影响到父组件当前组件及其子组件,因为它会将组件的样式应用到全局样式中,从而影响到整个应用程序。 
 
然而,ViewEncapsulation.None 不会影响到其他组件。其他组件仍然会使用它们自己的样式封装方式(默认是 ViewEncapsulation.Emulated),并且不会受到 ViewEncapsulation.None 的影响。

组件交互 暂时没看

组件样式

  • :host (相对于组件模板内部的元素)

image-20230705160101078
text
导入组件
import { Component } from '@angular/core'
@Component({
  selector: 'app-custom-component',
  template: '<h1>Hello, I am a custom component!</h1>',
  host: {
    class: 'custom-class',
    style: 'color: red;'
  }
})
export class CustomComponent { }
  • :host-context (判断父级是否有相关再应用)

image-20230705161027059
:host-context是Angular中的一个CSS伪类选择器,用于选择宿主元素的特定上下文。它允许您根据宿主元素的上下文选择应用样式。
 :host-context选择器的语法如下:
 阿萨德
:host-context(selector) {
  /* 样式规则 */
}
在选择器中,selector是一个CSS选择器,用于选择宿主元素的父级元素或祖先元素。只有当宿主元素的父级元素或祖先元素匹配选择器时,样式规则才会应用于宿主元素。
 这个选择器的作用类似于CSS中的 `:has` 选择器,但是它可以选择宿主元素的上下文,而不仅仅是父级元素。
 下面是一个使用:host-context选择器的示例:
css
:host-context(.parent-class) {
  /* 样式规则 */
}
在这个例子中,宿主元素只有在其父级元素具有 `.parent-class` 类时才会应用这些样式规则。
 :host-context选择器非常有用,特别是当您希望根据宿主元素的上下文选择应用样式时。它允许您根据组件在不同上下文中的使用情况来调整样式。
 希望这个解释对您有帮助!如果您有任何其他问题,请随时提问。
  • :host ::ng-deep
image-20230705162153660

内容投影 (插槽 ) 有条件的投影没研究

插槽就是在[自定义组件]中预留一个位置,这个位置的内容可以由使用组件的人来定义,具有高度的灵活性。

  • 单插槽(组件内html存放位置)

    image-20230706161145359

使用select选择想要插入的内容

image-20230706162854058
标签中的 select 属性来定义插槽的选择器。选择器可以是元素选择器、类选择器或属性选择器。

- 元素选择器:使用元素名称作为选择器。例如, <ng-content select="div"></ng-content> 将选择所有 <div> 元素。 

- 类选择器:使用类名前缀加上点号作为选择器。例如, <ng-content select=".my-class"></ng-content> 将选择所有具有 my-class 类的元素。 

- 属性选择器:使用属性名前缀加上方括号作为选择器。例如, <ng-content select="[my-attribute]"></ng-content> 将选择所有具有 my-attribute 属性的元素。 
 
您还可以通过组合选择器来更精确地选择插槽中的内容。例如, <ng-content select="div.my-class"></ng-content> 将选择所有同时具有 div 元素和 my-class 类的元素。 
 
在父组件中,您可以使用相应的选择器来为每个插槽定义内容。例如, <div slot="header">Header Content</div> 将将 Header Content 投影到具有 slot="header"`选择器的插槽中。
image-20230706164842290

ng-template 和ng-container

<ng-template>和<ng-container>是Angular中的两个常用指令,它们在功能上有一些区别。
 <ng-template>是一个结构指令,用于定义一个可重用的模板。它通常用于结合其他指令(如*ngIf和*ngFor)来创建动态的内容。您可以将<ng-template>视为一个占位符,它不会直接在DOM中渲染任何内容,而是在需要时根据条件或循环来渲染。
 示例:
<ng-template #myTemplate>
  <p>This is a template</p>
</ng-template>
 <ng-container *ngTemplateOutlet="myTemplate"></ng-container>
在上面的示例中,我们定义了一个名为myTemplate的<ng-template>,它包含一个段落元素。然后,我们使用*ngTemplateOutlet指令将该模板插入到<ng-container>中。当条件满足时,<ng-template>中的内容将被渲染到DOM中。
 <ng-container>是一个容器指令,它用于在不引入额外的DOM层级的情况下组织和管理内容。它的作用类似于一个无需添加额外元素的<div>容器。与<div>不同的是,<ng-container>不会在渲染时创建任何额外的DOM元素。它仅用于包裹和组织内容,并提供一些功能,例如结构指令(如*ngIf和*ngFor)的使用。
 示例:
<ng-container *ngIf="condition">
  <p>This is rendered if condition is true</p>
</ng-container>
在上面的示例中,当条件为true时,<p>元素将被渲染到DOM中。由于<ng-container>本身不会创建任何额外的DOM元素,因此在渲染时不会添加任何不必要的元素。
 总结:
- <ng-template>用于定义可重用的模板,通常与*ngTemplateOutlet指令一起使用。
- <ng-container>用于组织和管理内容,通常与结构指令(如*ngIf和*ngFor)一起使用。
 希望这个解释对您有帮助!如果您有任何其他问题,请随时提问。
image-20230706171237728image-20230707142524546
-  `[ngTemplateOutlet]` :这是一个输入属性,用于指定要渲染的模板。您可以将一个模板引用赋值给它,然后该模板将被渲染在指定的位置。

可以存放template相关引用

-  `[ngOutletContext]` :这是一个输入属性,用于指定模板上下文。它可以是一个对象,包含要在模板中使用的变量和方法。在模板中,您可以通过这些变量和方法来访问和操作上下文中的数据。
`[ngOutletContext]`  是 Angular 中的一个属性绑定,用于传递上下文对象给指令或组件。它通常与结构型指令(如  `ngFor` 、 `ngIf` )一起使用。
 当使用结构型指令时,可以使用  `[ngOutletContext]`  属性将一个对象作为上下文传递给指令或组件。这个上下文对象可以在指令或组件内部使用,并且可以通过特定的变量名进行访问。
 下面是一个示例,展示了如何使用  `[ngOutletContext]`  属性:
html
<ng-container *ngFor="let item of items; index as i; let isFirst = first; let isLast = last">
  <app-item [item]="item" [ngOutletContext]="{ index: i, isFirst: isFirst, isLast: isLast }"></app-item>
</ng-container>

在上面的示例中, `*ngFor`  结构型指令用于遍历  `items`  数组,并为每个元素创建一个  `<app-item>`  组件实例。

通过使用  `[ngOutletContext]`  属性,我们将一个对象传递给  `<app-item>`  组件,该对象包含了当前遍历的索引  `i` ,以及布尔值变量  `isFirst`  和  `isLast` ,用于判断当前元素是否是第一个或最后一个。

 在  `<app-item>`  组件中,我们可以通过特定的变量名来访问传递的上下文对象。例如,我们可以在组件的模板中使用  `index` 、 `isFirst`  和  `isLast`  变量来访问相应的值。
 希望这个解释对您有帮助。如果您对这个问题还有其他疑问,请随时提问。
image-20230707155416781

暂时的理解通过 [ngOutletContext]将对象数据传递给 组件内部

image-20230707161711934
ng-container 可以定义contex 和let-变量将属性传递给mytemplate模板变量  差不多可以当作父子通信

注意:*ngTemplateOutlet 指令只能用于渲染在 、、、、ng-template 标签中定义的模板。在模板中,您可以使用 let- 前缀来声明模板的上下文变量,以便在使用 *ngTemplateOutlet 渲染时传递数据。

Angular 元素(Elements)概览 动态加载的方式添加弹窗,另一个使用自定义元素的方式

模板

  • property 绑定 -@input
  • 模板变量
<label>Type something: 
  <input #customerInput>{{customerInput.value}} 
</label>
模板引用变量是Angular中的一种特殊语法,用于在模板中引用HTML元素或组件。
在这个例子中,通过在输入框元素上添加模板引用变量 #customerInput,
可以在模板中引用该输入框的值。在这里,我们通过{{customerInput.value}}来获取输入框的值并显示在模板中。
这样,我们可以在模板中对输入框的值进行操作或展示。
  • Attribute 绑定
image-20230710110753108
  • 样式绑定
image-20230710112418538image-20230710112825222image-20230710145408022
  • 双向绑定
image-20230710161109828

Angular的双向绑定和ngModel之间有一些区别。让我们来看看它们的定义和举例来更好地理解。 双向绑定是Angular中的一种特性,它允许数据在组件和模板之间进行双向的同步更新。当数据在组件中改变时,模板中的对应部分也会更新;反过来,当用户在模板中改变数据时,组件中的对应数据也会更新。 ngModel是Angular中的一个指令,它用于建立双向绑定。它通常用于表单元素(如输入框、复选框等),以便将用户输入的值同步到组件中的属性,并将组件中的属性值反映到模板中。 举个例子,假设你有一个简单的登录表单,其中包含一个输入框用于用户名和一个输入框用于密码。你想要实现双向绑定,以便当用户在输入框中输入用户名时,组件中的属性也会更新;同时,当组件中的用户名属性改变时,输入框中的值也会更新。 html

<input type="text" [(ngModel)]="username">
<input type="password" [(ngModel)]="password">

在这个例子中, [(ngModel)] 指令用于实现双向绑定。它将输入框中的值与组件中的 usernamepassword 属性进行绑定。当用户在输入框中输入内容时,组件中的属性值会自动更新;反之亦然,当组件中的属性值改变时,输入框中的值也会自动更新。 总结起来,双向绑定是Angular的一种特性,而ngModel是用于实现双向绑定的指令。它们一起工作,使得数据在组件和模板之间的同步变得简单和高效。 希望这个例子能帮助你理解双向绑定和ngModel之间的区别。如果你还有其他问题,请随时提问!

管道

http

在某些情况下,我们可能不需要使用 .subscribe() 来订阅 this.http.get(url) 这样的请求。这通常发生在以下几种情况下:

  1. 使用 Angular 的异步管道(AsyncPipe):Angular 提供了一个异步管道,可以直接在模板中处理异步数据。当我们在模板中使用 this.http.get(url) 并将其与异步管道一起使用时,Angular 会自动订阅并处理返回的数据。这样我们就不需要显式地使用 .subscribe() 来订阅请求了。 例如,在模板中使用异步管道:
html
<div>{{ this.http.get(url) | async }}</div>
  1. 使用 HttpClient 的其他方法:除了 .get() 方法之外,HttpClient 还提供了其他方法,如 .post().put().delete() 等。这些方法会自动订阅并处理返回的数据,因此不需要额外的 .subscribe() 。 例如,使用 .post() 方法发送请求:
  this.http.post(url, data).subscribe(
    (response) => {
console.log("Response:", response);
// 在这里处理返回的数据
    },
    (error) => {
console.error("Error:", error);
// 在这里处理错误情况
 }
);
  1. 使用 RxJS 操作符:RxJS 提供了许多操作符,如 mapfilterreduce 等,可以对 Observable 进行转换和处理。在使用这些操作符时,我们可以通过链式调用它们来处理返回的数据,而无需使用 .subscribe() 。 例如,使用 map 操作符对返回的数据进行转换:
  this.http.get(url).pipe(
    map((data) => {
// 在这里对返回的数据进行转换
return transformedData;
  })
  ).subscribe(
    (transformedData) => {
console.log("Transformed data:", transformedData);
// 在这里处理转换后的数据
    },
    (error) => {
console.error("Error:", error);
// 在这里处理错误情况
 }
);

需要注意的是,如果我们不使用 .subscribe() 来订阅请求,那么请求实际上不会发送,也不会执行任何操作。因此,在需要发送请求并处理返回数据的情况下,我们仍然需要使用 .subscribe() 来订阅请求。 希望这个解答能够帮助你理解在什么情况下不需要使用 .subscribe() 来订阅 this.http.get(url) 这样的请求!如果还有其他问题,请随时提问。

Contributors

Yuan Tang