在上一篇文章中我介紹了安裝和結構,以及運行過程。
https://blog.csdn.net/weixin_42603009/article/details/94382945
我們進一步理解其中的數據單向、雙向、組建傳值、Modules等的理解。
將你新建的項目用vs或者webStorm打開。
查看package.json,找到scripts中的運行命令運行。(另外這個json中還有依賴的包)
運行後訪問:http://localhost:4200/
這裏面有教你如何快速創建組件,添加UI組件,添加依賴。
ng generate component xyz ---快速創建組件
ng add @angular/material --添加UI組件
ng add @angular/pwa --PWA(Progressive Web App,漸進式網頁應用)是一種理念,使用多種技術來增強web app的功能,可以讓網站的體驗變得更好,能夠模擬一些原生功能,比如通知推送。在移動端利用標準化框架,讓網頁應用呈現和原生應用相似的體驗。
ng add _____ 添加依賴的,+依賴名字
瞭解完基礎。我們開始進一步理解。
1,快速創建組件(Modules):(注意需要選擇好目錄)
比如:組件是父子關係是相對關係。
此外還有如下命令(他們也有各自屬性,用時瞭解):
ng generate class my-new-class: 新建 class
ng generate component my-new-component: 新建組件
ng generate directive my-new-directive: 新建指令
ng generate enum my-new-enum: 新建枚舉
ng generate module my-new-module: 新建模塊
ng generate pipe my-new-pipe: 新建管道
ng generate service my-new-service: 新建服務
創建好後我們來分析下:
因此我們就可以在app.component.html中使用:
運行結果如下:
那麼如果我想在mymodule1中用my-input又該如何?我們可以看到MyInputComponent也在app中申明瞭。換句話來所,我們模擬它的運行過程,自定給my-input建module文件。如下面過程。(推薦使用第二種)
首先到指定目錄下創建:
G:\angularStu\myAngular>cd src
G:\angularStu\myAngular\src>cd APP
G:\angularStu\myAngular\src\app>CD owncomponent
// 這裏可以使用mkdir創建一個目錄。
G:\angularStu\myAngular\src\app\owncomponent>ng generate component my-input
CREATE src/app/owncomponent/my-input/my-input.component.html (23 bytes)
CREATE src/app/owncomponent/my-input/my-input.component.spec.ts (636 bytes)
CREATE src/app/owncomponent/my-input/my-input.component.ts (282 bytes)
CREATE src/app/owncomponent/my-input/my-input.component.css (0 bytes)
UPDATE src/app/app.module.ts (682 bytes)
// 上面方法過於麻煩。其實你還可以這樣。目錄也跟着創建了(推薦使用)
G:\angularStu\myAngular>ng g component components/header
CREATE src/app/components/header/header.component.html (21 bytes)
CREATE src/app/components/header/header.component.spec.ts (628 bytes)
CREATE src/app/components/header/header.component.ts (275 bytes)
CREATE src/app/components/header/header.component.css (0 bytes)
UPDATE src/app/app.module.ts (770 bytes)
G:\angularStu\myAngular>
如何創建:
對hmtl經行編寫:
<p>my-input works!</p>
<input type="text" placeholder="請輸入姓名">
運行結果:
放在app.component.html中也是可以的。
<div>
<app-mymodule1></app-mymodule1>
<app-mymodule2></app-mymodule2>
<app-my-input></app-my-input>
</div>
運行結果:
這裏特別再強調一點。如上我早my-app中要用到FormsModule組件。我們必須取它所在module中sheng’ming聲明。再app.module.ts中是不會有用的。
到此組件創建和引用,以及外部組件引用的細節都知道了。
2,路由:頁面的跳轉。
路由:路由就是根據不同url地址。動態的讓根組件掛載其他組件來實現一個單頁面應用。
1,創建組件,並在app-routing.module.ts添加路由:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {AppComponent} from './app.component';
import {AdminComponent} from './components/admin/admin.component';
import {HomeComponent} from './components/home/home.component';
import {NewsComponent} from './components/news/news.component';
// 自定義路由
const routes: Routes = [
//不要寫成‘/admin’
{path: 'admin', component: AdminComponent},
{path: 'home', component: HomeComponent},
{path: 'news', component: NewsComponent},
// 默認路由
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
路由跳轉方式:
<style>
</style>
<div>根組件</div>
<div>
<!--兩種方式,一個靜態,一個動態,效果一樣。這裏要加/-->
<!-- routerLinkActive="active" 是實現選中-->
<a [routerLink]="['/news']" routerLinkActive="active">去到news</a><br>
<a routerLink="/admin" routerLinkActive="active">去到admin</a>
<router-outlet></router-outlet>
訪問結果:
那麼跳轉如何傳值呢?
首先我們新建一個newsDetail看靠如上配置路由。實現有news到newsDetail傳值。
1.get方式傳值:[queryParams]="data"的方式。
news組件中:
<p>news works!</p><br><br><br>
<a [routerLink]="['/newsDetails']" [queryParams]="data">跳轉到newsDetails</a>
<!--下面的也是可以的-->
<!--<a routerLink="/newsDetails" [queryParams]="data">跳轉到newsDetails</a>-->
<--推薦使用下面這種-->
<!--<a [routerLink]="['/newsDetails', data]">跳轉到newsDetails</a>-->
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {
public data: any = {
zhouyi: '真帥',
}
constructor() { }
ngOnInit(): void {
}
}
點擊結果:
newDetails界面獲取值:
import { Component, OnInit } from '@angular/core';
// 1.引入ActivatedRoute
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-news-details',
templateUrl: './news-details.component.html',
styleUrls: ['./news-details.component.css']
})
export class NewsDetailsComponent implements OnInit {
constructor(
public route: ActivatedRoute
) { }
ngOnInit(): void {
// 2.獲取方式。和我們的http請求是類似的。
this.route.queryParams.subscribe((data) => {
console.log(data);
});
// 如果第三種是params獲取
// this.route.params.subscribe((data) => {
// console.log(data);
// });
}
}
2.js方法中跳轉。
新建一個adminLogin組件。同上路由配置等。
admin組件:
<p>admin works!</p>
<br><br><br>
<button (click)="goToAdminDetails()">跳轉到adminDetail</button>
import { Component, OnInit } from '@angular/core';
// 1.引入Router get傳值用NavigationExtras
import {Router, NavigationExtras} from '@angular/router';
@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit {
public data: any = [1, 2, 3];
// 2.構造(先寫構造)
constructor(public router: Router) { }
ngOnInit(): void {
}
goToAdminDetails(): void {
// 3.路由跳轉
// this.router.navigate(['/adminLogin/', this.data]);
// get方式跳轉.這個參數格式很嚴格。如下。
// 當然不引入NavigationExtras也是可以的。
// 比如
// let queryParams= {
// queryParams: {'aid': 123}
// };
let queryParams: NavigationExtras = {
queryParams: {'aid': 123}
};
this.router.navigate(['/adminLogin'], queryParams);
}
}
結果:
重點父子路由(嵌套路由)的理解:
最簡單的父子路由以CSDN舉例:點擊1,對應的2出現,2對應的3出現。也就是在1控制2,2控制3典型父子路由。
具體看如下圖:
附上命令:
ng g component components/home
ng g component components/home/welcomeHome
ng g component components/home/systemSet
ng g component components/news
ng g component components/news/newslist
ng g component components/news/newsfast
結果:
這裏我需要特意說明兩點:
1、當前組件指定掛載組件位置:通過它根據需要掛載到位置。
<router-outlet></router-outlet>
2、全局樣式最好放在styles.css下。
3,dom操作
首先,我回憶下原生js的操作。
// 我們用的是document操作,
// 比如:獲取dom id = "tmpId" 也可以用class獲取。
var dom = document.getElementById('tmpId');
dom.setAttribute('title','titleName'); // 各種屬性都可以這麼設置
dom.style.color='red';
dom.getAttribute('title'); // 結果爲titleName
// 爲<div id ="fileId"></div> 插入html
var str = ‘<span>’ + nihao + '</span>';
dom.innerHTML = str; // innerTEXT也是可以的。看你需求
// 另外我們獲取的dom結構類似如下。這個就需要你有類似經驗。
在angular中的dom操作 (ViewChild)。
1,首先給要獲取的結點取名。形式: #name
consoleDom是用來獲取結構的
<div #mymoudule>
<p>mymodule1 works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</p>
<p (click)="consoleDom()">test</p>
</div>
2,業務邏輯處理(對應的ts):
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
@Component({
selector: 'app-mymodule1',
templateUrl: './mymodule1.component.html',
styleUrls: ['./mymodule1.component.css']
})
export class Mymodule1Component implements OnInit {
// 通過裝飾器@ViewChild獲取dom結點。 兩種寫法都可以推薦第一種。取出dom給了mydom
@ViewChild('mymoudule') mydom: ElementRef;
// @ViewChild('mymoudule') mydom: any;
constructor() { }
ngOnInit(): void {
}
consoleDom() {
console.log(this.mydom);
}
}
結果如下:
ViewChild的另一個更大的用處。父子組件通過ViewChild調用子組件。
<app-header #header></app-header>
<div #mymoudule>
<p>mymodule1 works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</p>
<p (click)="consoleDom()">test</p>
</div>
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
run() {
console.log('我是子組件,該方法在父組件被調用');
}
}
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
@Component({
selector: 'app-mymodule1',
templateUrl: './mymodule1.component.html',
styleUrls: ['./mymodule1.component.css']
})
export class Mymodule1Component implements OnInit {
// 通過裝飾器@ViewChild獲取dom結點。 兩種寫法都可以推薦第一種。
// 取出dom給了mydom
@ViewChild('mymoudule') mydom: ElementRef;
// 獲取子組件
@ViewChild('header') myheader: ElementRef; // 得到了子組件所有
// @ViewChild('mymoudule') mydom: any;
constructor() { }
ngOnInit(): void {
}
consoleDom() {
console.log(this.mydom);
// 調用子組件的方法
this.myheader.run();
}
}
4,angular中css動畫
側邊欄的實現:
G:\angularStu\myAngular>ng g component components/asidetranstion
CREATE src/app/components/asidetranstion/asidetranstion.component.html (29 bytes)
CREATE src/app/components/asidetranstion/asidetranstion.component.spec.ts (684 bytes)
CREATE src/app/components/asidetranstion/asidetranstion.component.ts (307 bytes)
CREATE src/app/components/asidetranstion/asidetranstion.component.css (0 bytes)
UPDATE src/app/app.module.ts (895 bytes)
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<style>
</style>
app.component.html
<div id="appID">
<app-asidetranstion></app-asidetranstion>
</div>
<router-outlet></router-outlet>
asidetranstion.component.html:
<div id="content">
主要內容
<button (click)="showAside()">展示側邊欄</button>
<button (click)="display()">展示側邊欄</button>
</div>
<aside #asideContent id="asideContent" style="width: 200px;height: 100%;position: absolute;right: 0px;top: 0px;background: red;transform: translate(100%,0);transition: all 2s">
這是側邊欄
</aside>
asidetranstion.component.ts:
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
@Component({
selector: 'app-asidetranstion',
templateUrl: './asidetranstion.component.html',
styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
@ViewChild('asideContent') myAside: ElementRef;
constructor() { }
ngOnInit(): void {
}
showAside() {
// this.myAside.style.transform = 'transform(0,0)';
document.getElementById('asideContent').style.transform = 'translate(0,0)';
}
display() {
document.getElementById('asideContent').style.transform = 'translate(100%,0)';
}
}
styles.css:
/* You can add global styles to this file, and also import other style files */
body{
width: 100%;
overflow-x: hidden;
}
5,父子組件通信(比較簡單一筆帶過)
1,父組件給子組件傳值—@input: 不僅可以把數據傳過去,還可以把自己的方法以及整個父組件傳給子組件。
舉個栗子:
父組件(父子):
// data代表值,也可以是方法。方法不能()表示直接執行。不帶調用則執行。
<app-header [data]="data"></app-header>
子組件接收:
@input data:any; // ts中 就可以用了
2,父組件獲取子組件值(前面已經講了@ViewChild): 不僅可以把數據傳過去,還可以把自己的方法以及整個父組件傳給子組件。 也可以用:Output 和EvenEmitter
子組件實例化(子父):
// 配合使用 string指定類型
@Output() private outer: new EvenEmitter<string>();
// 在方法中將要給父組件的值發送出去
this.outer.emit('子組件的值傳給父組件');
父組件接收:
<app-header (outer)="Menthod($event)"></app-header>
非父子組件的通信:推薦用service或者loaclstorage(推薦前者)
6,rxjs異步數據流遍程
它的強大體現在將一切數據,包裝爲數據流。它比promise更爲強大。
異步遍程排序:回調函數,事件監聽/發佈訂閱,Promise,Rxjs。
回調函數實現:
1,首先我們創建一個service:
G:\angularStu\myAngular>ng g service service/request
CREATE src/app/service/request.service.spec.ts (362 bytes)
CREATE src/app/service/request.service.ts (136 bytes)
2,在service方法中定義自己的方法:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class RequestService {
constructor() { }
// t同步方法
getData() {
return '獲取數據';
}
// 異步方法
getCallbackData() {
setTimeout(() => {
return '異步方法';
}, 1000);
}
// 異步方法,回調函數實現獲取異步值
getCallbackData111(cd) {
setTimeout(() => {
return cd('異步方法');
}, 1000);
}
}
3,在哪裏用你就在哪裏的constructor中說明引入。即可用。
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
@Component({
selector: 'app-asidetranstion',
templateUrl: './asidetranstion.component.html',
styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
@ViewChild('asideContent') myAside: ElementRef;
constructor(
public request: RequestService
) { }
ngOnInit(): void {
console.log(this.request.getData());
// 異步不能獲取到,爲undefined
console.log(this.request.getCallbackData());
// 異步回調實現
this.request.getCallbackData111((data) => {
console.log(data);
});
}
showAside() {
// this.myAside.style.transform = 'transform(0,0)';
document.getElementById('asideContent').style.transform = 'translate(0,0)';
}
display() {
document.getElementById('asideContent').style.transform = 'translate(100%,0)';
}
}
結果如下:(這也跟緩存的原理有點類似)
2,promise實現(位置和上面一樣,這是ES中自帶的方式):
const promiseData = this.request.getPromiseData().then((data) =>{
console.log(data)
})
getPromiseData() {
return new Promise((res => {
setTimeout(() => {
res('promise應用');
});
}));
}
結果:
3。Rxjs實現異步(和promise很類似,結果省略):但是他可以取消訂閱.unsubscribe()規定沒返回就撤銷。
const promiseData = this.request.getObservableData().subscribe((data) =>{
console.log(data);
});
getObservableData() {
return new Observable((observe) => {
setTimeout(() => {
observe.next('observe調用數據');
});
});
}
Rxjs還可以多次執行。比如一個請求每隔幾秒發送一次。
異步請求封裝定時器
getObservableData() {
return new Observable((observe) => {
// 每隔一秒出發一次
setInterval(() => {
const name = '張三';
observe.next(name);
}, 1000);
});
}
結果:
3,管道對map,filter的應用。
如果你懂java流操作,講一下就會。
filter是對數據操作過濾;map是對數據進行操作改變:
const promiseData = this.request.getObservableData().pipe(filter(value => {
if (value % 2 == 0) {
return true;
}
}), map(value => {
// 比如在這裏將對象轉爲json
return value*value;
})).subscribe((data) =>{
console.log(data);
});
結果:
7,數據請求
通常我們會將請求封裝都一個地方。
但無非是如下過程:
前提需要在app.module.ts引入模塊支持。
get請求如下:
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
// 引入HttpClient
import { HttpClient} from '@angular/common/http';
@Component({
selector: 'app-asidetranstion',
templateUrl: './asidetranstion.component.html',
styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
@ViewChild('asideContent') myAside: ElementRef;
constructor(
public request: RequestService,
// 申明
public http: HttpClient
) { }
ngOnInit(): void {}
httpRequest() {
this.http.get('localhost:8080/test').subscribe((res: any) => {
console.log(res);
});
}
}
post如下(需要設置請求數據,header):
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
// 引入HttpClient,HttpHeaders頭組件
import { HttpClient, HttpHeaders} from '@angular/common/http';
@Component({
selector: 'app-asidetranstion',
templateUrl: './asidetranstion.component.html',
styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
@ViewChild('asideContent') myAside: ElementRef;
constructor(
public request: RequestService,
// 申明
public http: HttpClient,
public header: HttpHeaders
) { }
ngOnInit(): void {}
httpRequest() {
const header = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
}
this.http.post('localhost:8080/test', {'data':'數據'}, header).subscribe((res: any) => {
console.log(res);
});
}
}
jsonp(解決跨域請求的一種方式):
需要在app.module.ts引入模塊支持;
import {HttpClientModule, HttpClientJsonpModule} from '@angular/common/http';
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
// 引入HttpClient,HttpHeaders
import { HttpClient, HttpHeaders} from '@angular/common/http';
@Component({
selector: 'app-asidetranstion',
templateUrl: './asidetranstion.component.html',
styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
@ViewChild('asideContent') myAside: ElementRef;
constructor(
public request: RequestService,
// 申明
public http: HttpClient,
public header: HttpHeaders
) { }
ngOnInit(): void {}
httpRequest() {
const header = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
}
// jsonp請求後臺必須支持jsonp請求
this.http.jsonp('localhost:8080/test', 'callback').subscribe((res: any) => {
console.log(res);
});
}
}
使用第三方詳情請見:https://blog.csdn.net/weixin_42603009/article/details/91477222