進一步理解angular

在上一篇文章中我介紹了安裝和結構,以及運行過程。
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章