preface

What advantages does Angular have over native JS? What is a single page application (SPA)?

Advantage:

  1. The project architecture is clear
  2. Code is highly reusable
  3. The code can be tested strong, you can add E2E tests, unit tests

Single-page applications offer advantages over previous requests for multiple HTML pages

  1. Good user experience, load all JS and CSS at once, content changes do not need to reload the entire page
  2. Front end separation

Angular development environment setup

In native JS, we usually use

The node installation

nodejs.cn/

You can run the node -v and NPM -v commands to check whether the installation is successfulCopy the code

Scaffolding installation

After Node is successfully installed, you can use the NPM command to install scaffolding

npm install -g @angular/cli  // Install the latest version
npm install -g @angular/[email protected] // You can also install the specified version
Copy the code

Create a new project and execute it

Ng new project_name // project_name Users can customize the project name CD project_name ng serve Enter http://localhost:4200 to view the related pageCopy the code

After entering the command, follow the following prompts to choose whether to create the project in strict mode. Second, whether to help you create the router file when creating the project; The third is what CSS type to code with. You can create it with the selection shown above.

Project Catalog Introduction

Component is introduced

Component concept

Before introducing components, let’s introduce themcomponentandThe moduleThe previous relationship, the framework is highly component-based development, all elements on the page can be seen as a component, the granularity of components in the specific page, or according to their own personal development habits. We know that in AngularApp moduleIs our root module, which manages the entire single-page application involvedOther modulesandcomponent. Let’s familiarize ourselves with the root module file app.module.ts.

@NgModule is an Angular decorator imported from ‘@angular/core’ : Help developers organize business code. Developers can use ngModules to organize tightly related components together. They can control not only components, but also directives, pipes, and so on.

  1. Declarations: a declaration of a component, directive, or pipe that must belong to a module and only one module.

  2. Imports: Used to import external modules instead of components.

  3. Exports: exports components, directives, modules, etc. If other modules import our module, then other modules can directly use the components we export here, instruction modules, etc.

  4. Providers: Here are all the services you need to use. Specify the service required at the root level of the application

  5. Bootstrap: Defines the startup component. You may have noticed that this configuration item is an array, which means you can specify a component as the starting point. Normally this doesn’t need to be changed.

As you can see, a single Angular page has a root module that contains many components, that is, multiple components make up a module.

Hello World and components

First let’s clear out the content in app.component.html for the rest of our component study.

1. In the app folder, create a component file named Hello-world.component.ts



From the above picture, we can know that the component consists of the following three parts:

  • Class (the name of the class is based on the filename of the component, camel name with a capital letter)

  • The @component decorator, imported from ‘@angular/core’, marks a class as an Angular component and configures it with metadata. There are only three metadata involved, including selector, also known as a selector. We can think of it as the name of our custom component, which is also the name of the app-component file. For more metadata applications, please refer to the official website.

  • An HTML template is a template.

2. As mentioned above, components must be declared in modules to be used properly, so I declare this in the root module



3. We will reference the defined components in the HTML of the app

At this point, the hello World page is perfectly displayed, and a simple component is wrapped.

Application of interpolation expressions in components

If a user does not want to display “Hello World” in the above component, how can it be dynamically displayed in the above component?

Angular uses interpolation to embed variables or expressions in text, using {{}} as delimiters by default

// hello-world.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: '<h1> {{title}} </h1>'.styles: ['h1 { color: red; } ']})export class HelloWorldComponent {
  public title = 'Learn Lesson 1 Angular';
}

Copy the code

When you open a browser page, you’ll see “Learn Angular Lesson 1” displayed on the page.

An introduction to the built-in directives in components

First of all, what is an instruction? Directives are classes that add additional behavior to elements in an Angular application. Attribute and structural directives are mainly introduced here. Attribute instruction:

  1. NgClass: Dynamically add and remove a set of CSS classes
// NgClass is used with expressions, and ngClassHasColor is used to determine whether ngclass-color should be added
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: ` 
      
Practice using ngclass
'
.styles: [ 'h1 { color: red; } '.'.ngclass-color {color: green}']})export class HelloWorldComponent { public ngClassHasColor = true; } Copy the code
  1. NgStyle: Dynamically add and remove a set of inline styles
1. import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: ` < div [ngStyle] = "{' color ', 'black', 'the font - size:' 18 px '}" > practice ngStyle use < / div > `.styles: []})export class HelloWorldComponent {}

// Or we can encapsulate multiple inline styles into an object so that we can dynamically control the values in the object,
// Simply assign the object variable directly to [ngStyle]
2. import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: '
      
Practice using ngStyle
'
.styles: []})export class HelloWorldComponent { public ngStyleObj = { 'color': 'black'.'font-size': '18px' }; } Copy the code
  1. NgModel: Adds two-way binding of data to HTML form elements

Structural instruction:

  1. NgFor: Repeat a loop to render a node
// In js, if we need to render a list, we need to manually iterate over the data and then dynamically generate the elements to render the list
// In Angular, we just use the NgFor syntactic sugar to loop through data
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: ` 
      
  • {{subject}}
`
.styles: []})export class HelloWorldComponent { public studySubjects = [ 'Setting up'.'Project Directory Introduction'.'Component Introduction'.'Introduction to nG-Zorro Component Library' ]; } // We can also get the index of the loop object and use it in the template, as follows: <ul> <li *ngFor="let subject of studySubjects; let i=index">{{ i+1 }} - {{ subject }}</li> </ul> Copy the code

The result of the loop is as follows:



2. NgIf: Creates or destroys subviews from a template. In layman’s terms, it controls the display and hiding of components or elements

// If there is a need:
// The loop list can be seen if the user is' backend '; Other users can't see it. How do you do that in Angular?
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: ` 
      
  • {{ i+1 }} - {{ subject }}
`
.styles: []})export class HelloWorldComponent { public userRole='backend'; // As long as the value of userRole is not backend, the above list is not displayed } Copy the code
  1. NgSwitch: Similar to switch logic in JS, it displays certain templates/views according to certain conditions

NgSwitch is a set of three properties: NgSwitch; NgSwitchCase; ngSwitchDefault

// Now if there is a need:
// if the age of the user is 12, it indicates that the user graduated from primary school
// If the user's age is 18, high school graduate is displayed
// If the user's age is 22, college graduate is displayed
// All other conditions are unknown
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: '
      
Graduated from primary school Graduated from high school University graduate unknown
'
.styles: []})export class HelloWorldComponent { public age = 18; // the page displays "graduated from high school" } Copy the code

Binding of properties in a component

In the above section, we found that many values wrapped in [], such as [ngClass] and [ngStyle], are actually wrapped in brackets, which we call attribute bindings. Its function is to dynamically set the attribute values of HTML elements or directives. Next, let’s look at property values that are common in development.

Base property binding

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

@Component({
  selector: 'app-hello-world'.template: `    `.styles: []})export class HelloWorldComponent {
  public itemImageUrl = '.. /.. /assets/bg.png';
  public isDisabledBtn = false;
  public spanText='Display the contents of the SPAN tag by property binding';
}

Copy the code

Attributes that bind to the class (recommended by developers and used frequently)

This method can dynamically add and remove single or multiple classes, similar to [ngClass], but much simpler

// Dynamically add a single class and multiple classes
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: '
      
attempt to bind a single class
attempt to bind multiple classes
'
.styles: [ '.bgColor{background-color: yellow}'.'.textcolor{color: red}']})export class HelloWorldComponent { public isSingleClass: boolean; public multipleClass = { // So only the bgColor class is in effect bgColor: true.textcolor: false}; }// The same is true for the style attribute Copy the code

Use of pipes in components

Pipes are used to convert and format strings, monetary amounts, dates, and other display data. These are simple functions that Angular provides with built-in pipe methods and custom pipe methods.

  • DatePipe: Formats date values according to the rules in the local environment.
  • UpperCasePipe: Converts all text to uppercase.
  • LowerCasePipe: Converts all text to lowercase.
  • CurrencyPipe: Converts a number to a currency string, formatted according to the rules in the local environment.
  • DecimalPipe: Converts a number to a string with a decimal point, formatted according to the rules in the local environment.
  • PercentPipe: Convert numbers to percentage strings, formatted according to the rules in the local environment.
// Take the date built-in pipe as an example
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: ` < p > xiao Ming's birthday is {{birthday | date}} < / p > < p > xiao Ming's birthday is {{birthday | date: "MM/dd/yy"}} < / p > `.styles: []})export class HelloWorldComponent {
  public birthday = new Date(1988.3.15);
}

/ / the resultXiao Ming's birthday is Apr15.1988Xiao Ming's birthday is04/15/88

Copy the code

The component’s birthday value through the pipeline operator (|) to date function. Date: The following values are the parameters passed into the pipe. If there are more than one parameter, you can split the incoming with more than one:

Component event binding – methods and parameters

Component event binding is much easier than native JS event binding. Let’s talk about how angular implements event binding

  1. Button event binding
// We want to implement an accumulator by clicking the button
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world'.template: {{curNumber}} '.styles: []})export class HelloWorldComponent {
  public curNumber = 1;

  public addCount(): void {
    this.curNumber++; }}Copy the code
  1. The $event object in the event binding

When writing a response event, you can accept a $event parameter, which is something about the response event.

<button (click)="addCount($event)"> The current value is added1</button>

 public addCount(event): void {
    console.log(event);
    this.curNumber++;
  }
Copy the code
  1. Parameter passing to the event
<button (click)="addCount($event, 5)"> The current value is added1</button>

 public addCount(event, paramsNumber: number): void {
     this.curNumber = this.curNumber + paramsNumber; // Add 5 each time
  }
Copy the code
  1. A button calls both methods simultaneously
// Use a semicolon to separate the two methods
<button (click)="addCount($event, 5); consoleCount()"> The current value is added1</button>

// Define two methods
 public addCount(event: any, paramsNumber: number): void {
    this.curNumber = this.curNumber + paramsNumber;
  }

  public consoleCount(): void {
    console.log(this.curNumber);
  }
Copy the code

How a component is declared

In the above example, we write the LOGIC of HTML, CSS and TS into the same file. In the real development process, if the logic is complicated, such inline component declaration is not recommended. In general, we usually use the form of external reference file, as shown below

// Template and style are both developed by introducing an outer layer of the file so that the HTML and CSS code can be developed in separate files
import { Component } from '@angular/core';

@Component({
  selector: 'app-outside-introduction'.templateUrl: './outside-introduction.component.html'.styleUrls: ['./outside-introduction.component.scss']})export class OutsideIntroductionComponent {}
Copy the code

Specific component OutsideIntroductionComponen created as follows:

Component’s parent component passes values

@input () and @Output() provide a way for child components to communicate with their parents. @input () allows the parent component to update data in the child component. In contrast, @output () allows a child component to send a number to its parent

A parent component passes a value to a child component throughattributeFor transmitting values

/ / app - outside - the introduction is app.com ponent subcomponents, now by this component to learn and spread value

// outside-introduction.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-outside-introduction'.templateUrl: './outside-introduction.component.html'.styleUrls: ['./outside-introduction.component.scss']})export class OutsideIntroductionComponent {
 // @input () is designed to implement value passing and needs to be introduced in '@angular/core '
 // This declaration means that you want to pass a value from the parent to showNumber in the HTML page where the parent introduces the child
  @Input() public showNumber: number;
}

// outside-introduction.component.html{{showNumber}}</div>Copy the code
// Parent component app.component.html<div> values in parent component: {{defaultNum}}</div><app-outside-introduction [showNumber] ="defaultNum"></app-outside-introduction>

// Parent component app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root'.templateUrl: './app.component.html'.styleUrls: ['./app.component.scss']})export class AppComponent {
  public defaultNum = 5;
}
Copy the code

The core code above is actually in two steps:

1.@input () public showNumber: number;2.The parent component is introduced via property binding to pass the variable defined in TS <app-outside-introduction [showNumber]="defaultNum"></app-outside-introduction>
export class AppComponent {
  public defaultNum = 5;
}
Copy the code

Child components pass values to parent components in the form of events

What if the child has the function of an accumulator and wants to pass internal accumulations to the parent and display them in the parent?

Child componentsimport { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-outside-introduction'.templateUrl: './outside-introduction.component.html'.styleUrls: ['./outside-introduction.component.scss']})export class OutsideIntroductionComponent {
  @Input() public showNumber: number;
  // The logic below implements self-organizing a value to the parent component
  @Output() public curCountChange = new EventEmitter<number>();
  public curCount = 1;
  public addCount(): void {
    this.curCount++;
    this.curCountChange.emit(this.curCount); }}Copy the code
The parent component// The event name curCountChange must be the same as @output ()
// '$event' is the value passed by the child component
<app-outside-introduction [showNumber]="defaultNum" (curCountChange)="handlCurCountChange($event)"></app-outside-introduction>

  public handlCurCountChange(value: number): void {
    // Value is the value passed by the child component
    this.valueFromChild = value;
  }
Copy the code

Detail @output in a single component

  • @Output()– a decorator function that marks this property as a way for data to pass from a child to a parent
  • curCountChange– this@Output()The name of the
  • EventEmitter<number>– this@Output()Is the data type passed by a child component to its parent
  • new EventEmitter<number>()– Use Angular to create a new event emitter that emits datanumberType.
  • curCountChange.emit()– Passes the value to the parent component via the emit method

Eventually the parent component accepts the value passed by the child component as an event

Bidirectional binding of components

Two-way binding is a special or more concise way of passing values between parent and child components. It uses the [()] syntax to combine property and event bindings. The only special point is their naming. Where input is the name of the corresponding @ input () attribute. For example, if the @input () attribute is size, the @Output() attribute must be sizeChange. Without going into too much detail here, we’ll go straight to bidirectional binding by looking at the most used form element [(ngModel)].

// The input is a component that Angular encapsulates. // The bidirectional binding [(ngModel)] is used if, Import {FormsModule} from '@angular/forms'; // import {FormsModule} from '@angular/forms'; <input [(ngModel)]="inputValue"> export class OutsideIntroductionComponent { public inputValue = 5; }Copy the code

Points to note about bidirectional binding:

The [(ngModel)] syntax can only set data binding properties. What if the user wants to do something extra when the value in the input box changes? ===> We can disassemble this combination mode as follows:

<input [(ngModel)]="inputValue" (ngModelChange)="consoleValue($event)">

  public consoleValue(value: string): void {
    console.log(value);
  }
Copy the code

Component life cycle

There are nine Life cycles for Angular components, but only three or four are used in real development. Today we’ll focus on the common ones

For details about the life cycle, see: Life Cycle Details

Use of TS in Angular components

In all of these files, we often see declarations of the public and void keywords, including the class we use in components. These are typeScript, but we often use ts definitions. Angular requires all variables, Functions are defined by type. First, let’s take a quick look at ts

Ts is a superType of JS, which means it is more formal and can be alerted to irregularities at compile time.



Some common type definitions:

The following are type annotations/type definitions: public a: number; public b: boolean; public c: string; public d: any; public e: number[] = [1, 2, 31]; public f: any[] = [1, true,'a', false]; Enum Color {Red, Green, Blue,} public backgroundColor = Color; // If backgroundcolor. Red is used, the value returned is 0, because enum is sorted in order by defaultCopy the code
Type inference. For simple types like these, ts can intelligently infer what type public curCount = 1 if it is assigned directly. public inputValue = 5;Copy the code

Introduce the NG-Zorro component library into your project

  1. Install the specified version of the component library NPM install [email protected] –save under this project

NPM install Analyzes the location of the installation file

  • npm install xxx: Installs the project into the project directory without writing module dependenciesdevDependenciesordependencies.
  • npm install -g xxx-gIs to install the module to the global, specific installation to the disk where, depending onnpm cinfig prefixThe location of the
  • npm install -save xxx:-saveInstall the module into the project directory and install it in thepackageOf the filedependenciesNode write dependency. Use this command when it is necessary on the project
  • npm install -save-dev xxx:-save-devInstall the module into the project directory and install it in thepackageOf the filedevDependenciesNode write dependency. This command is used when a dependency is needed during development
  1. Introduce this component in app.module

3. Introduce component styles in the global style.scss file

/* You can add global styles to this file, and also import other style files */
@import "~ng-zorro-antd/style/index.min.css"; /* Introduce basic styles */
@import "~ng-zorro-antd/button/style/index.min.css"; /* Introduces component styles */
Copy the code
  1. Introduce SVG and styles in angular.json files
{ "assets": [{..."glob": "* * / *"."input": "./node_modules/@ant-design/icons-angular/src/inline-svg/"."output": "/assets/"}]."styles": [..."node_modules/ng-zorro-antd/ng-zorro-antd.min.css"]}Copy the code

For a more detailed introduction of UI components, see Quick Installation of NG-Zorro-ANTd