Angular
The performance of Google's open source JavaScript library is much higher than that of the previous version. It uses Typescript and new mode for development, so from the second version, the number of people has suddenly dropped dramatically.
Technology: basic use of typescript, es6
Typescript is a superset of JavaScript. Both JavaScript content and es6 can be used directly in typescript.
Typescript code still needs to be compiled into pure JavaScript, and typescript compilation tools can run on any server and any system. Typescript open source
Typescript:
1. Very inclusive, JavaScript
2. Define everything from simple to complex.
3. If typescript reports an error, it can still generate a JavaScript file
4. typescript has an active community.
Disadvantages of typescript:
- High learning cost
- Short term projects, simple projects, inefficient.
- The compatibility with other libraries is not high.
Install typescript
cnpm install -g typescript
Create suffix as. Finally, the files of ts need to be converted to js through compilation
Compile TS file into js
tsc index.ts
Install angular cli
cnpm install -g @angular/cli
Create project
ng new angularApp --skip-install
Installing the module
npm install
Start development service command
Npm start
Open browser at startup
ng serve --open
Create component command
ng g component component/news
Component usage:
<app-news></app-news>
Typescript data type
Original data type: Boolean, numeric, string, null, undefined;
Boolean type definition: note that it is possible to call Boolean directly
let isDone:boolean = true; isDone = false; let isCheck:boolean = Boolean(1)
Error mode: because new Boolean returns 1 object type
let isCheck:boolean = new Boolean(1)
Numerical type definition
let num:number = 1; let num16:number = 0xf00a; let notNum:number = NaN; let infNum:number = Infinity;
String type definition
let username:string = 'laochen'; let age:number = 30; let juzi:string = `My age is ${age}`;
Null value: in most cases, it is used to define a function without a return value, but not a variable. Once a variable is defined as a void type, it can only be evaluated as undefined or null;
//Null value function hello():void{ console.log('helloworld') } let unable:void = undefined; unable = null;
Null and undefined definitions
//null and undefined types, not significant let a:undefined = undefined; a = null; let b:null = null; b = undefined;
Note: null and undefined are subtypes of all types. void type cannot be assigned to other types, although it only has undefined and null, for example
let username:string = 'laochen'; username = undefined; let abc:undefined = undefined; let cba:void = undefined; username = abc; //username = cba; / / this is not allowed because cba is of void type let age:number = 30;
Any value type
Any value type is used to indicate that any value type assignment is allowed.
//Any value type let admin:any = 'adbc' admin = 123; //Any value type allows access to any of its properties let anything:any = 'hello'; console.log(anything.myname);
Variable of undeclared type
let something1; //something1 will be defined as any value type if it has no defined type or assigned value at the time of declaration something1 = 'abc'; something1 = 123;
Type inference
//Although no type is defined when something2 is declared, because the assignment is a string, typescript has type inference rules, which will define the assignment type as the variable type let something2 = 'abc'; //something2 = 123; / / an error will be reported
Union type: indicates that multiple types can be selected.
let cat:string|number; cat = 'little cat'; cat = 1; let cat1:string|number = 'little cat';
Typescript interface
What is an interface? The abstraction of behavior. Concrete actions need to be implemented by classes (content abstracted from interfaces).
Equivalent to defining the description of the class.
definition:
interface Person{ name:string; age:number; } let tom:Person = { name:"tom", age:16, } //To constrain the TOM object, it must be consistent with the interface properties. //The initial of a general interface is capitalized. //For objects defined with interfaces, attributes cannot be written more or less
Interface optional attribute: this attribute can be written, can not be written, but can't be written more. Add? that will do
//Optional interface properties interface Student{ name:string; age?:number; } let s1:Student = { name:"Xiao Ming", age:16, }
Interface can define any attribute
//Any attribute interface Teacher{ name:string; age?:number; [propName:string]:any; } let t1:Teacher={ name:"Lao Wang", age:35, school:'tsinghua' }
Read only property, readonly
interface Cat{ //Read only property. It can only be assigned once. It cannot be modified later, but it can be obtained readonly name:string; color:string; age:number; } let c1:Cat = { name:'Persian cat', color:"white", age:10 } //C1. Name = 'chinchilla'; / / an error will be reported because c1.name is a read-only attribute
Typescript function
typescript restricts the input and output of functions,
Input and output will define type, parameter input (parameter definition type), return value (definition type)
//typescript restricts the input and output of functions, //Input and output will define type, parameter input (parameter definition type), return value (definition type) function sum1(x:number,y:number) :number{ return x+y; } let result:number = sum1(3,4);
Function expression writing
//Function expression writing let sum2 = function(x:number,y:number) :number{ return x+y; } //In this way, only anonymous functions on the right side are defined. There is no substantial definition of the left sum2 variable; let sum3:(x:number,y:number) => number = function(x:number,y:number) :number{ return x+y; }
Optional parameter, plus?
//Optional parameters function sumName(firstname:string,lastname?:string):string{ return firstname+lastname; } sumName('lao',"chen"); sumName('lao'); //Note: the optional parameter must be placed after the required parameter. It is not allowed to place the required parameter after the optional parameter //not allow // function sumName2(lastname?:string,firstname:string,):string{ // return firstname+lastname; // }
Parameter default
//Default parameters function sumName3(firstname:string='chen',lastname:string='guan'):string{ return firstname+lastname; }
Remaining parameters
//Remaining parameters //ES6 normal mode function fnpush(...items){ } function fnpush1(...items:any[]):string{ return 'abc'; }
heavy load
//heavy load //Overload allows 1 function to receive different numbers or types of parameters function setAbc(x:number|string):number|string{ return x; } function fnAbc(x:boolean):boolean; function fnAbc(x:number):number; function fnAbc(x:string):string; function fnAbc(x:any):any{ if(typeof x==='number'){ return x; }else{ return x } } fnAbc('1') fnAbc(false)
class
//Define static methods class Animal{ static isAnimal(a){ return a instanceof Animal; } } let dog = new Animal(); Animal.isAnimal(dog); //typescript static properties class Dog{ static age =20; } console.log(Dog.age) //Class properties class Abc{ a = 1; b = 3; private c = 4; constructor(){ this.a = 1; this.b = 2; this.c = 3; } } //Properties can be decorated with three modifiers, public/private/protect //Public. It can be accessed anywhere. By default, all properties are public //Private, private, can only be accessed in the content of the class, not outside the class //Protected, protected. protect can be accessed in subclass. private is not allowed class Banana{ private name; public constructor(name){ this.name = name; } } let aa = new Banana('Hainan banana'); //console.log(aa.name) / / cannot be obtained. name is a private property //aa.name = 'Paris Banana' / / cannot be accessed, name is a private property class Apple{ protected name; public constructor(name){ this.name = name } } //protect allows access in subclasses. class BigApple extends Apple{ private constructor(name){ super(name) console.log(this.name) } } //If constructors are private, they cannot be instantiated //let bb = new BigApple('aaaa'); //Abstract class. Abstract classes are not allowed to be instantiated. They are generally used for inheritance and implementation. abstract class PinkPig{ public name; constructor(name){ this.name = name } //Define only, not implement public abstract sayHi(); } class SmallPinkPig extends PinkPig{ sayHi(){ console.log("helloworld") } }
Angular_css
Note: Componet.css is only used for components, style.css global style under src root directory
Angular template syntax
MVVM design pattern originated from MVC.
- >Model: data (model) / status
V - > View: View
C - > controller: how to modify data interactively
MVVC
M->model
V->view
vm - > bi directional binding of data and view. As long as the data is modified, vm (framework) will automatically change the view, and the view interaction changes the data.
Angular interpolation
Syntax: {{... Variables and expressions}}
Application: it can be applied to html content or property
<h1 [innerHtml]="htmlStr"></h1>
Angular style
The three defined methods of class are consistent with VUE, and will automatically add variables to the original HTML class
<!-- How to define variables --> <h1 class="abc" class="{{classStr}}">class1</h1> <h1 class="abc" [class]="classStr">class2</h1> <h1 [attr.class]="classStr">class3</h1>
Class variable type
<!-- Variable type --> <!-- String pattern --> <h1 [class]="classStr">class4</h1> <h1 class="a" [class]="'str abc'">class4</h1> <!-- Object mode --> <h1 [class]="classObj">class5</h1> <h1 [class]="{bgBlue:isShow}">class6</h1> <!-- Array mode --> <h1 [class]="['bgBlue','active','abc']">class7</h1> <h1 [class]="classArr"></h1>
Style
<!-- style --> <!-- style Expression type --> <!-- String variable --> <h1 [style]="styleStr"></h1> <!-- Object mode --> <h1 [style]="styleObj"></h1> <!-- orange --> <h1 [style.height]="styleObj.width">h</h1> <h1 [style.width]="colorAbc"></h1> <h1 [style.width.px]="widthNum"></h1>
Event
<!-- Binding event: Write the bracket on the left side of the equal sign plus the event name, and write the called event function on the right side --> < button (click) = "changecolor()" > change color < / button > < button (click) = "changebutton ($event)" > change color < / button >
Exercise code used above
isShow = true; classArr = ['abc','cba','aaa']; styleStr = "background:skyblue;width:400px;height:400px;"; styleObj = { background:"pink", width:'100px', height:"100px" }; colorAbc='100px'; widthNum = 200; changeColor(){ this.styleObj = { background:"purple", width:'200px', height:"300px" }; } changeButton(event){ console.log(event) event.target.style.background = 'green' }
conditional rendering
<!-- conditional rendering --> <!-- person If it's Cantonese, it shows the epidemic information of Cantonese --> <div *ngIf="person=='Cantonese'"> Guangdong: 1000 </div> <div *ngIf="person=='Hubei people'"> Hubei: 40000 </div> <button (click)="togglePerson()">Switch identity</button> <h1>style Conditional rendering of</h1> <!-- The conditional rendering used here will remove the Document,Add to DOM Will consume performance. --> <!-- Use STYLE For conditional rendering, if you need to switch content frequently, you need to style Finish conditional rendering--> <div [style.display]="person=='Cantonese'?'block':'none'"> Guangdong: 1000 </div> <div [style.display]="person=='Hubei people'?'block':'none'"> Hubei: 40000 </div> <!-- Conditional rendering, matching multiple situations --> <div [ngSwitch]="homeState"> <div *ngSwitchCase="'Sleep'">Bedroom</div> <div *ngSwitchCase="'Watch tv'">A living room</div> <div *ngSwitchCase="'Having dinner'">Restaurant</div> <div *ngSwitchCase="'In a daze'">balcony</div> <div *ngSwitchDefault>Toilet</div> </div> <!-- Conditional rendering, matching multiple situations --> <div [ngSwitch]="orderState"> <div *ngSwitchCase="1">To be paid</div> <div *ngSwitchCase="2">Paid</div> <div *ngSwitchCase="3">Deliver goods</div> <div *ngSwitchCase="4">Received goods</div> <div *ngSwitchDefault>Lose</div> </div>
Loop rendering
<!-- List loop --> <ul> <li *ngFor="let item of arr">{{item}}</li> </ul> <!-- List loop get index value --> <ul> <li *ngFor="let item of arr;let i=index">Index value:{{i}};Content:{{item}}</li> </ul> <!-- Passing the contents of a list into an event --> <ul> <li *ngFor="let item of arr;let i=index" (click)="choosePerson(item,i)">Index value:{{i}};Content:{{item}}</li> </ul> <!-- Loop complex array --> <ul> <li *ngFor="let item of students;let key=index">{{key}}-{{item.name}}My hobby is{{item.hobby}}</li> </ul>
Angular data bidirectional binding
Import module to app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; //Import form module import { FormsModule} from '@angular/forms' import { AppComponent } from './app.component'; import { NewsComponent } from './views/news/news.component'; @NgModule({ declarations: [ AppComponent, NewsComponent ], //Import imports: [ BrowserModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Data binding of forms
<input type="text" [(ngModel)]="username">
Set temporary variables to bind DOM objects
<!-- Form data acquisition --> <div> <label for="">user name</label> <input #input1 type="text" > </div> <div> <label for="">Password</label> <input #input2 type="text" > </div> <button (click)="getContent(input1.value,input2.value)">Get account password</button>
NgForm gets the data of the whole form. NgForm can only be used in the form
<form action="" #formobj> <input type="text" [(ngModel)]="username" name="username" > <input type="text" [(ngModel)]="password" name="password" > <button (click)='eventFn(formobj)'>Button</button> </form>
Pipe (similar to vue filter)
Converting objects to json format display <h1>{{student | json}}</h1> Convert time to yy/MM/dd format <h1>Display time: {time | date: "YY / mm / DD"}}}</h1> Capitalize <h1>User name: {{username | uppercase}}}</h1> //Pipes can be converted multiple times <h1>{{'abcdefg'|uppercase|lowercase}}</h1>
Custom pipe
Create a custom pipe file
ng g pipe filter/lcUppercase
import { Pipe, PipeTransform } from '@angular/core'; // @Pipe({ // name: 'lcUppercase' // }) // export class LcUppercasePipe implements PipeTransform { // transform(value:string,...args:string[]):string { // if(value = = "Lao Chen"){ // return "handsome old Chen" // } // return value ; // } // } @Pipe({ name: 'lcUppercase' }) export class LcUppercasePipe implements PipeTransform { transform(value:string,...args:string[]):string { console.log(args) return '¥'+value+args[0]; } }
Template
Note: msg is the template variable, lcUppercase is the conversion function, followed by: parameter
<h1>{{msg|lcUppercase:'element'}}</h1> //msg=100 //According to the above customized pipeline, the result is ¥ 100
Pass value from parent component to child component
//Pass parameters in the parent component (html) <app-child [item]="sendchildMsg"></app-child> //(ts) value in parent component sendchildMsg ="This is the data for the child element. You want to display it in the child component"; //Subcomponent import Input import {Input} from '@angular/core'; export class ChildComponent implements OnInit { //@The function of input is to define module input, which is used to let parent components pass content to child components. @Input() item; } //Subcomponent (html) <h1>{{item}}</h1> //The displayed result is: This is the data for the child element, and you want to display it in the child component
Data transfer from child component to parent component
//Subcomponent template (. html) <button (click)="sendMsg()">Send message to parent</button> //Subcomponent logic (. ts) //Output is used to mark a class field as an output attribute and provide configuration metadata. Any DOM attribute bound to the output attribute will be automatically updated by Angular during change detection. //angular provides EventEmitter to trigger custom events. The child instruction creates an EventEmitter instance and exports it as an output attribute. The child instruction calls the emit(payload) method in the created EventEmitter instance to trigger an event. The parent instruction listens for the event through event name and gets the payload object through the $event object. //Import import {Output,EventEmitter } from '@angular/core'; export class ChildComponent implements OnInit { //instantiation @Output() childMsg=new EventEmitter() //Custom events sendMsg(){ this.childMsg.emit({msg:"My child component. This is the message I sent to the parent component"}) } } //Parent component template <h1>Information sent by subcomponent:{{getChildMsg}}</h1> //Listening event, customized by childMsg <app-child (childMsg)="getEvent($event)"></app-child> //Parent component logic export class AppComponent { getChildMsg=""; getEvent(event){ console.log(event) this.getChildMsg = event.msg } }
Life cycle function
constructor(){ console.log("Component constructor call") } ngOnChanges(){ console.log("This function is called when the data changes ngOnChanges") } ngOnInit(){ console.log("Once the data binding and instruction input properties are displayed for the first time, they are called, once only") } ngDoCheck(){ console.log('stay ngOnChanges and ngOnInit After that, a test will be carried out') } ngAfterContentInit(){ console.log('After the data content is rendered to the view') } ngAfterContentChecked(){ console.log('Data content rendered after view detection') } ngAfterViewInit(){ console.log('Complete initialization of components and subcomponents') } ngAfterViewChecked(){ console.log('After component and subcomponent initialization detection') } ngOnDestory(){ console.log("Destroy component") }
Custom instruction
To create an instruction file:
ng g directive directive/lcstyle
Set command content and function
//Parent component <h1 [appLcstyle]="'abc'"></h1> //ElementRef as the name implies is the element reference. //In fact, in the practical application, it is to obtain the dom elements of the view layer. With the help of the dependency injection mechanism provided by August, it is easy to access the dom elements. //Subcomponent direct import { Directive,Input,ElementRef } from '@angular/core'; //Custom instruction @Directive({ selector: '[appLcstyle]' }) export class LcstyleDirective { @Input() appLcstyle; constructor(public ref:ElementRef) { console.log('ref') //Will output dom elements } //Life cycle function ngOnChanges(){ //console.log(this.appLcstyle) //console.log(this.ref) this.ref.nativeElement.className = this.appLcstyle; this.ref.nativeElement.innerHTML = this.appLcstyle; this.ref.nativeElement.addEventListener("click",()=>{ this.ref.nativeElement.style.background="pink" }) } }
Custom services: many components need to be abstracted from common functions (classes and functions)
1. Create service file
ng g service service/stocklist
service
import { Injectable } from '@angular/core'; import axios from 'axios' @Injectable({ providedIn: 'root' }) export class StockListService { constructor() { } async getAllStocks(){ let httpUrl = 'http://localhost:8080/stocklist'; let result = await axios.get(httpUrl); return result.data.data; } async superStocks(){ let httpUrl = 'http://localhost:8080/superStock'; let result = await axios.get(httpUrl); return result.data.data; } }
2. Import service into project
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { LcstyleDirective } from './directive/lcstyle.directive'; //Import service into project import { StockListService } from './service/stock-list.service' @NgModule({ declarations: [ AppComponent, LcstyleDirective ], imports: [ BrowserModule ], //Import service providers: [ StockListService ], bootstrap: [AppComponent] }) export class AppModule { }
Using services to get data
import { Component } from '@angular/core'; import axios from 'axios'; import {StockListService} from './service/stock-list.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'angularapp'; stockList = [] superStocks = [] //Injection service constructor( public stockSer:StockListService ){ // let httpUrl = 'http://localhost:8080/stocklist'; // axios.get(httpUrl).then((res)=>{ // console.log(res.data) // this.stockList = res.data.data.slice(0,10) // console.log(this.stockList) // }) stockSer.superStocks().then((res)=>{ this.superStocks = res.slice(0,10) }) } async stockFn(){ console.log(123) let allStocks = await this.stockSer.getAllStocks() this.stockList = allStocks.slice(0,10) } }
page
<button (click)="stockFn()">Get 10 stock list</button> <h1>Ten stocks expected to rise or fall today</h1> <div *ngFor="let item of superStocks"> <h1>Share name:{{item.stockName}}</h1> <h2>Stock Code:{{item.stockCode}}</h2> <div class="img"> <img src="{{item.dailyChart}}" alt=""> <img src="{{item.hourlyChart}}" alt=""> </div> </div> <h1>Common stock</h1> <div *ngFor="let item of stockList"> <h1>Share name:{{item.stockName}}</h1> <h2>Stock Code:{{item.stockCode}}</h2> <div class="img"> <img src="{{item.dailyChart}}" alt=""> <img src="{{item.hourlyChart}}" alt=""> </div> </div>
Routing configuration
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import {IndexComponent} from './view/index/index.component'; import {AboutComponent} from './view/about/about.component'; import {NewsComponent} from './view/news/news.component' //Configure routing objects const routes: Routes = [ { //No need to add/ path:"", component:IndexComponent }, { path:'about', component:AboutComponent }, { path:"news", component:NewsComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
HTML template
<!-- Display different components according to path changes --> <style> div>span{ margin: 20px; padding: 5px 10px; background-color: skyblue; } </style> <div> <span [routerLink]="['/']" routerLinkActive="router-link-active" >home page</span> <span [routerLink]="['/about']" routerLinkActive="router-link-active" >about</span> <span [routerLink]="['/news']" routerLinkActive="router-link-active" >news</span> </div> <router-outlet></router-outlet>
Dynamic routing
{ //Dynamic routing path:"news/:id", component:NewsComponent },
Get parameters of dynamic route
import { Component, OnInit } from '@angular/core'; //Import route import {ActivatedRoute} from '@angular/router' @Component({ selector: 'app-news', templateUrl: './news.component.html', styleUrls: ['./news.component.less'] }) export class NewsComponent implements OnInit { title = "" //Inject route constructor(public route:ActivatedRoute) { //http://localhost:4200/news/123?search=meinv#abc //console.log(this) } ngOnInit(): void { //console.log(this) //let params = this.route.params; //console.log(params.value.id); } goParams(){ //Use parameters this.route.params.subscribe((params)=>{ console.log(params) this.title = params.id; }) } }
Sub route
{ path:'admin', component:AdminComponent, children:[ { path:'user', component:UserComponent }, { path:'product', component:ProductComponent } ] },
HTML template settings
<p>admin works!</p> <style> .admin{ display: flex; height: 600px; } .admin .left{ width: 200px; background: skyblue; } .admin .main{ flex:1; background: lavenderblush; } </style> <div class="admin"> <div class="left"> //This is the sidebar <div [routerLink]="['/admin/user']" routerLinkActive="router-link-active" >user</div> <div [routerLink]="['/admin/product']" routerLinkActive="router-link-active" >product</div> </div> <div class="main"> <router-outlet></router-outlet> </div> </div>
Programming navigation, how JS controls route jump
1 / dependency injection router
import { Component, OnInit } from '@angular/core'; //Import route import {ActivatedRoute,Router} from '@angular/router' @Component({ selector: 'app-news', templateUrl: './news.component.html', styleUrls: ['./news.component.less'] }) export class NewsComponent implements OnInit { title = "" //Route, route constructor(public route:ActivatedRoute,public router:Router) { //http://localhost:4200/news/123?search=meinv#abc console.log(this) this.route.data.subscribe((data)=>{ console.log(data) this.title = data.msg }) } ngOnInit(): void { //console.log(this) //let params = this.route.params; //console.log(params.value.id); } goParams(){ this.route.params.subscribe((params)=>{ console.log(params) this.title = params.id; }) } goHome(){ //The first parameter is the passed in array (array of paths) this.router.navigate([''],{ queryParams:{ usernam:"admin" }, fragment:"abc", replaceUrl:true }) } }
//The first parameter is the incoming array (the array of paths), which is automatically spliced into a complete path this.router.navigate([''],{ //Splicing parameters queryParams:{ usernam:"admin" }, fragment:"abc",//Pass hash value //Do you want to replace the current page replaceUrl:true })