【Angular】提供给Vue用户的Angular教程

在学习框架时,我们会采取一种学习方法,就是类似于在Vue中该功能是如何实现的,那么在这个框架中又是如何实现的呢…

我最近正在学习Angular,整理了一些类似于Vue中的内容,并写了一篇文章。在与Vue进行比较的同时,我也介绍了Angular的基础知识。希望能对开始学习Angular的同伴们有所帮助!(^。^)

在这篇文章中介绍了React中“如同Vue中的…”的内容,请务必一起查看!✨

Angular 的定義是

angular-logo-1.png

如何启动Angular应用

请执行以下命令,以创建并运行Angular应用程序。

npm init @angular {アプリケーション名}

当你执行该命令时,会启动一个交互式命令行界面,要求你选择路由配置和样式语言。根据你想创建的应用程序的需求进行选择后,应用程序的创建将开始。

> ? Would you like to add Angular routing? (y/N)
> ? Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS 
  SCSS   [ https://sass-lang.com/documentation/syntax#scss                ] 
  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ] 
  Less   [ http://lesscss.org

如果你看到下面的输出,表示应用程序已经成功创建。如果出现“command not found: npm”错误,这意味着你的执行环境中没有安装Node.js和npm。请参考这篇文章进行安装后,再次执行下面的命令。

...
CREATE my-first-app/src/app/app.module.ts (393 bytes)
CREATE my-first-app/src/app/app.component.css (0 bytes)
CREATE my-first-app/src/app/app.component.html (23115 bytes)
CREATE my-first-app/src/app/app.component.spec.ts (1091 bytes)
CREATE my-first-app/src/app/app.component.ts (216 bytes)
✔ Packages installed successfully.
    Successfully initialized git.

请在安装完成后,转到创建的应用程序目录。

cd {アプリケーション名}

当执行以下命令时,Angular开发服务器将在localhost:4200上启动(如果端口4200已被占用,则会使用其他端口)。

npm start
> my-first-app@0.0.0 start
> ng serve

✔ Browser application bundle generation complete.

Initial Chunk Files   | Names         |  Raw Size
vendor.js             | vendor        |   2.04 MB | 
polyfills.js          | polyfills     | 314.28 kB | 
styles.css, styles.js | styles        | 209.41 kB | 
main.js               | main          |  48.10 kB | 
runtime.js            | runtime       |   6.52 kB | 

                      | Initial Total |   2.60 MB

Build at: 2023-05-03T05:01:09.540Z - Hash: d570b7afea270a79 - Time: 4150ms

** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **


✔ Compiled successfully.
Screen Shot 2023-05-03 at 14.07.48.png

同样,通过使用AngularCLI工具,可以让Angular应用开发更加轻松愉快。我建议您进行安装。有关AngularCLI的详细说明,请参阅此处的官方文档。

npm install -g @angular/cli

组件基础

在Angular中,一个组件由TypeScript文件,HTML文件和CSS文件组成。在Vue中,模板标签、脚本标签和样式标签分别存在于不同的文件中。听起来有点麻烦,但是通过使用AngularCLI,可以轻松创建组件。
请在应用程序的目录中执行以下命令。

ng generate component {コンポーネント名}

只要输出以下内容,就表示组件的自动生成已经完成。在创建组件时,需要在app.module.ts中注册组件,但这也会自动进行修正。非常方便。

CREATE src/app/hello/hello.component.css (0 bytes)
CREATE src/app/hello/hello.component.html (30 bytes)
CREATE src/app/hello/hello.component.spec.ts (656 bytes)
CREATE src/app/hello/hello.component.ts (237 bytes)
UPDATE src/app/app.module.ts (509 bytes)

此外,使用上述命令还会生成spec文件。由于这是用于测试实现的文件,请根据需要进行生成。你可以通过添加–skip-tests选项来阻止生成spec文件。

ng generate component {コンポーネント名} --skip-tests

Angular中,我写到了一个组件由一个TypeScript文件、一个HTML文件和一个CSS文件组成,但是在TypeScript文件中也可以表示模板。由于本文主要介绍如何将文件分开,所以请理解。

import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  template: `
    <h1>Hello Component</h1>
  `,
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
}

在Vue中,所指的”data”

在TypeScript文件的组件类中,通过将其定义为成员变量,可以实现与data相同的功能。

import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
  message = 'Hello World!';
  flag = false;
}

在使用组件时,请按照以下方式使用。

<p *ngIf="flag">{{ message }}</p>

在Vue中所说的methods

在TypeScript文件中的组件类中,通过定义方法来实现与methods相同的功能。
当在方法内部访问成员变量(data)时,要像Vue一样使用this.{要访问的数据}进行编写。

import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
  message = 'Hello World!';

  helloWorld(): void {
    alert(this.message);
  }
  saySomething(something: string): void {
    alert(something);
  }
}

在使用HTML文件中的方法时,请按照以下方式进行描述。

<button (click)="helloWorld()">HelloWorld!</button>
<button (click)="saySomething('Something!!')">SaySomething!</button>

在Vue中所指的computed

在Angular中,通常会介绍使用带有get关键字并定义getter方法来模拟Vue的computed属性。但在下面的情况中,在控制台中会多次输出“numberToDisplay called.”,即使返回值相同,也反复进行重新计算。Vue的computed属性具有缓存功能。如果在Vue中进行如下实现,则只会在控制台中输出一次,并且在依赖数据不发生变化的情况下不会再次进行计算。(在这篇文章中对computed属性的缓存功能进行了清晰明了的解释!)因此,使用带有get关键字的getter方法来模拟computed属性并不能产生适当的效果。根据我的调查,似乎没有找到一种能够复制缓存行为的方法,如果有了解的人,请务必留下评论。

import { Component } from '@angular/core';

@Component({
  selector: 'app-user',
  template: `
    <p>{{ numberToDisplay }}</p>
    <p>{{ numberToDisplay }}</p>
    <p>{{ numberToDisplay }}</p>
    <p>{{ numberToDisplay }}</p>
  `,
  styleUrls: ['./user.component.css'],
})
export class UserComponent {
  number: number = 0;

  get numberToDisplay(): number {
    console.log('numberToDisplay called.');
    return this.number + 1;
  }
}

在Vue中,所谓的props

通过使用@Input装饰器,可以将数据从父组件传递给子组件。在下面的例子中,我们定义了一个名为name的属性并将值”Test props”从父组件传递给子组件。

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  @Input() name: string = '';
}
<p>{{ language }}</p> <!-- Test props -->
<app-child name="Test props"></app-child>

此外,如果要将变量绑定到子组件的传值中,则需要使用方括号[]将属性名称包围起来,如下所示。

<app-child [language]="propToChild"></app-child>
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
  propToChild = 'Hello';
}

在Vue中,所谓的emit

通过使用@Output装饰器和EventEmitter类,可以定义自定义事件(emit)。在下面的例子中,我们定义了一个名为“close”的自定义事件,并在子组件的按钮被点击时触发了该事件。你可以使用this.{eventName}.emit()来触发已定义的事件。

<button (click)="onClickClose()">Close</button>
import {
  Component,
  EventEmitter,
  Output
} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
})
export class ChildComponent {
  @Output() close = new EventEmitter<any>();

  onClickClose(): void {
    this.close.emit();
  }
}
<app-child language="propToChild" (close)="onEmitClose()"></app-child>
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
  onEmitClose(): void {
    alert('Emitted!!!');
  }
}

在事件触发时传递参数值的实现方式如下。

<button (click)="onClickClose(args)">Close</button>
import {
  Component,
  EventEmitter,
  Output
} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
})
export class ChildComponent {
  @Output() close = new EventEmitter<string>();

  onClickClose(): void {
    this.close.emit('Hello');
  }
}
<app-child language="propToChild" (close)="onEmitClose($event)"></app-child>
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
  onEmitClose(args): void {
    alert(args);
  }
}

在Vue中,可以理解为watch。

在Angular中,似乎没有检测到以成员变量的方式定义的值(相当于Vue中的data)的更改的方法(如果有的话,请务必告诉我)。然而,可以通过使用ngOnChanges()方法和@Input()从父组件接收的值(相当于Vue中的props)来检测变化。

要使用ngOnChanges()方法,需要实现OnChange接口。

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent implements OnChanges {
  @Input() name = '';

  ngOnChanges(changes: SimpleChanges): void {
    console.error('Changed:', changes);
  }
}
<p>Name: {{ name }}</p>
import { Component } from '@angular/core';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent {
  parentName: string = '';
}
Name: <input type="text" [(ngModel)]="parentName"/>
<app-hello [name]="parentName"></app-hello>

ngOnChanges()方法接收一个名为SimpleChanges对象的参数。您可以通过这个对象获取每个属性的旧值(previousValue)和新值(currentValue)。ngOnChanges()方法在@Input()属性初始化时也会执行,因此它在组件初始化时一定会执行一次。这时,firstChange属性会被设为true。

{
  "name": {
    "previousValue": "a",
    "currentValue": "aa",
    "firstChange": false
  }
}

在Vue中所说的components

在Vue中,通常我们会在每个组件的components选项中添加要使用的子组件,而在Angular中,通常会在app.module.ts文件中指定要使用的组件,以便可以从所有组件中使用所有组件。

在@NgModule()装饰器的declarations选项中添加导入的类,即可完成组件的注册。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello/hello.component';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { UserComponent } from './user/user.component';
import { ChildComponent } from './child/child.component';
import { ParentComponent } from './parent/parent.component';
import { TestComponent } from './test/test.component';

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent,
    UserComponent,
    ChildComponent,
    ParentComponent,
    TestComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    RouterModule.forRoot([]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

指令

在Vue中,与@click相对应的是

使用click事件可以定义当元素被点击时要触发的事件。使用的形式是(click)=”触发的事件”。以下示例中,当按钮被点击时,执行了方法hello。

<button (click)="hello()">
  Button
</button>

在Vue中,当写成@click=”hello”时,事件对象将作为方法的参数传递,但在Angular中,需要明确地将$event作为参数传递,如下所示。

<button (click)="hello($event)">
  Button
</button>

在Vue中,相当于v-model

使用ngModel可以将变量绑定到表单的输入上。您可以像这样使用[(ngModel)]=”要绑定的变量”。下面的例子中,我们将变量name绑定到文本表单上。

<input type="text" [(ngModel)]="name" />

使用ngModel时,需要在app.module.ts中定义FormsModule如下。如果不定义,将会输出错误信息: Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello/hello.component';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

在Vue中被称为v-for

通过使用ngFor来表示循环。可以使用*ngFor=”let element of loopObj”这样的形式来使用。以下代码中,将显示带有ngFor的元素的次数为someArr的元素数量。

<div *ngFor="let item of someArr">
  {{ item }}
</div>

在Vue中可以使用v-if

通过使用ngIf,可以根据条件来决定元素的显示。使用形式为*ngIf=”条件”。下面的示例中,如果isAngular为true,则会显示具有ngIf条件的元素以下内容。

<div *ngIf="isAngular">
  <p>Hello Angular!</p>
</div>

在Vue中的说法是created/mounted

使用ngOnInit()能够在组件初始化时挂钩并执行一次处理。
要使用ngOnInit(),需要在组件类中实现OnInit接口。通过实现该接口,可以使用ngOnInit()方法。

import { Component, OnInit } from '@angular/core';
import axios from 'axios';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent implements OnInit {
  users = [];

  ngOnInit(): void {
    this.getUsers();
  }

  async getUsers(): Promise<void> {
    try {
      const { data } = await axios.get('/api/users');
      console.log(data);
    } catch (e) {
      console.error(e);
    }
  }
}

请参考官方文档以了解有关生命周期挂钩的信息。

路由(相当于Vue中的VueRouter)

最初的设置

在Vue中,我们需要安装VueRouter来进行路由操作,而在Angular中,我们可以进行路由操作而无需安装额外的软件包。在这里,我们将介绍路由引入的代表例。
请将RouterModule.forRoot()添加到app.module.ts文件的@NgModule()装饰器的imports中。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot([])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

接下来,在src/app/app.component.html文件中添加 router-outlet 标签(就像Vue Router中的 router-view 一样)。

<router-outlet></router-outlet>

只需将路由信息作为数组形式添加到RouterModule.forRoot()的参数中,路由设置就完成了。路由信息应指定一个包含路径(path)和要显示的组件(component)的对象,具体如下所示。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { HelloComponent } from './hello/hello.component';

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: 'hello',
        component: HelloComponent
      }
    ])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

另外,如果要指定路由器的路径参数,可以在路径中使用:paramName的形式进行指定。

{
  path: 'users/:userId',
  component: UserComponent
}

搬迁

在Vue中,相当于

在Angular中,没有像VueRouter的标签那样的准备。相反,路由指令会添加到a标签上。要指定转换到的目标,请使用routerLink。您可以将定义的路径(在路由定义时指定的路径)指定为routerLink的值,从而可以转到相应的屏幕。

<a routerLink="/users">Users</a>

如果要指定路径参数,可以使用链接参数数组。通过将routerLink括在[]中,可以将数组值指定为链接的值。将导航目标的路径放在数组的第一个元素中,将路径参数放在第二个元素中。在以下情况下,导航目标的URL将是”/users/1″。

<a [routerLink]="['/users', 1]">Users</a>

在Vue中,相当于this.$router.push()的是什么?

在 TypeScript 中进行页面导航时,我们使用 navigate() 方法。我们需要将 navigate() 的参数设置为与 routerLink 指定的内容相同的值。

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css'],
})
export class HelloComponent {
  constructor(private _router: Router) {}

  jumpToUserPage(): void {
    this._router.navigate(['/users', 1]);
  }
}
广告
将在 10 秒后关闭
bannerAds