主頁 > 企業開發 > 玩轉Angular系列:組件間各種通信方式詳解

玩轉Angular系列:組件間各種通信方式詳解

2023-03-03 08:24:57 企業開發

前言

在前端框架Angular中,組件之間的通信很基礎也很重要,不同組件間的通信方式也不同,掌握組件間的通信方式會更加深刻的理解和使用Angular框架,

本文講解不同型別組件間的不同通信方式,文中所有示例均提供原始碼,您可以 在線編輯預覽下載本地除錯,相信通過本文您一定可以掌握組件通信這一知識點,

父組件傳子組件

@Input方式

@Input()裝飾器允許父組件更新子組件中的資料,分為4步:

第一步:在父組件app.component.ts中定義要傳遞給子組件的資料parentMsg

export class AppComponent {
  parentMsg: string = 'parent component message!';
}

第二步:在父組件app.component.html中的子組件標簽<app-child>中定義屬性[childMsg](子組件接收資料變數)來系結父組件的資料parentMsg

<app-child [childMsg]="parentMsg"></app-child>

第三步:在子組件child.component.ts中引入@Input()裝飾器,修飾childMsg接收父組件的傳值,

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

export class ChildComponent {
  @Input() childMsg: string = '';
}

第四步:在子組件child.component.html中通過模板標簽{{childMsg}}展示資料,

<div>父組件傳值內容:{{ childMsg }}</div>

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

說明:這里要理解父組件html中通過[]定義了一個子組件的屬性,該值必須與子組件中所定義的變數名一致,而等號右邊的值為父組件要傳遞的屬性名,示例中是將父組件中parentMsg的值系結在子組件childMsg屬性上,

子組件傳父組件

@Output()方式

@Output()裝飾器允許資料從子組件傳給父組件,分為6步:

第一步:在子組件child.component.ts中引入OutputEventEmitter,通過@Output()來修飾一個EventEmitter實體的變數newItemEvent

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

export class ChildComponent {
  @Output() newItemEvent = new EventEmitter<string>();
}

第二步:在子組件child.component.html中添加點擊事件,獲取輸入內容,點擊按鈕觸發addNewItem()方法,

<label>輸入專案名:<input type="text" #newItem /></label>
<button type="button" (click)="addNewItem(newItem.value)">
  添加專案到父組件
</button>

第三步:在子組件child.component.ts中通過newItemEventemit()方法,把資料發送到父組件,

export class ChildComponent {
  @Output() newItemEvent = new EventEmitter<string>();
  
  addNewItem(value: string) {
    this.newItemEvent.emit(value);
  }
}

第四步:在父組件app.component.html中子組件標簽<app-child>中添加父組件方法addItem($event)系結到子組件的newItemEvent發射器事件上,其中$event為子組件的傳遞的值,

<app-child (newItemEvent)="addItem($event)"></app-child>

第五步:在父組件app.component.ts中通過addItem($event)方法獲取處理資料,

export class AppComponent implements AfterViewInit {
  items = ['item1', 'item2', 'item3'];
  
  addItem(newItem: string) {
    this.items.push(newItem);
  }
}

第六步:在父組件app.component.html中遍歷items展示資料,

<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

說明:這里要理解關鍵的第四步事件連接(newItemEvent)="addItem($event)"含義,左側是父組件監聽子組件創建的一個發射器newItemEvent,右側是父組件的addItem($event)方法,子組件通過發射器的emit(value)方法廣播傳遞值到父組件,父組件通過addItem($event)中的$event接收傳值,完成通信,

本地變數方式

在父組件模板里,新建一個本地變數來代表子組件,可以利用這個變數來讀取子組件的屬性和呼叫子組件的方法,分為2步:

第一步:在子組件child.component.ts中定義count變數和addOne()方法,

export class ChildComponent {
  count: number = 0;
  addOne() {
    this.count++;
  }
}

第二步:在父組件app.component.html中子組件標簽<app-child>中添加本地變數#child,點擊按鈕觸發點擊事件,通過本地變數呼叫子組件方法child.addOne()

<app-child #child></app-child>
<button type="button" (click)="child.addOne()">加1</button>

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

說明:在子組件標簽中通過#+變數名的方式新建一個本地變數代表子組件的參考,本地變數方式使用簡單明了,但也有局限性,只能在模板html中使用,無法在ts檔案中使用,

@ViewChild方式

通過@ViewChild裝飾器,將子組件注入到父組件,分為4步:

第一步:在子組件child.component.ts中定義count變數和add()方法,

export class ChildComponent {
  count: number = 0;
  add(num: number) {
    this.count = this.count + num;
  }
}

第二步:在父組件app.component.html中子組件標簽<app-child>中添加標簽參考#child,點擊按鈕觸發點擊事件,執行方法add()

<app-child #child></app-child>
<button type="button" (click)="add(2)">加2</button>

第三步:在父組件app.component.ts中引入ViewChild@viewchild傳入標簽參考字符child,由變數child接收,除了使用標簽參考child,你也可以通過直接傳入子組件ChildComponent實作子組件的參考,

import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child/child.component';

export class AppComponent {
  // 第一種方法:傳入組件參考名child
  @ViewChild('child') private child: any;
  // 第二種方法:傳入組件實體ChildComponent
  @ViewChild(ChildComponent) private child: ChildComponent;
}

第四步:在父組件app.component.ts中方法add()中呼叫子組件的add()方法,

export class AppComponent {
    add(num: number) {
        this.child.add(num);
    }
}

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

說明@ViewChild的作用是宣告對子組件元素的實體參考,意思是通過注入的方式將子組件注入到@ViewChild容器中,你可以想象成依賴注入的方式注入,只不過@ViewChild不能在構造器constructor中注入,因為@ViewChild()會在ngAfterViewInit()回呼函式之前執行,我們可以測驗下:

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from './child/child.component';

export class AppComponent implements AfterViewInit {
  @ViewChild('child') private child: any;

  constructor() {
    console.log('constructor func', this.child); // undefined
  }

  ngAfterViewInit() {
    console.log('ngAfterViewInit func', this.child); 
  }
}

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

通過列印結果我們可以看到在建構式constructor()中,this.child的值為undefined,并沒有注入到父組件,但在ngAfterViewInit()生命周期鉤子中注入成功了,

不相關組件

對于不相關聯的組件,我們會使用其他中間媒介的方式進行通信,以下不相關組件的通信方式仍適用于父子組件,

service服務方式

組件間共享一個service服務,那么組件之間就可以通過service實作通信,

示例中我們使用rxjs中的BehaviorSubject,它是Subject的一種變體,可以存盤最后一條資料或者初始默認值,并會在訂閱時發送其當前值,您可以通過RxJS官網進行了解,當然通過文中的說明,您還是可以了解其具體實作的功能,

我們創建兩個不相關的組件AB,組件A發布資料,組件B接收資料,通過服務檔案data.service.ts進行關聯實作,

在公共檔案目錄下創建service服務檔案data.service.ts,代碼如下:

import { Injectable } from '@angular/core';
// 1.引入
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  // 2.創建subject
  subject: BehaviorSubject<any> = new BehaviorSubject<any>(0);

  constructor() {}
}

引入BehaviorSubject,創建一個BehaviorSubject, 默認值設為0, 記得在app.module.ts檔案中引入公共data.service.ts檔案,并宣告,

import { DataService } from './data.service';

@NgModule({
  providers: [DataService],
})
export class AppModule {}

創建組件A,用于發布資料,a.component.ts實作代碼如下:

import { Component } from '@angular/core';
// 1. 引入
import { DataService } from '../data.service';

@Component({
  selector: 'app-a',
  templateUrl: './a.component.html',
})
export class AComponent {
  // 2. 注冊
  constructor(public dataService: DataService) {}

  inputValue: string = '';

  send(): void {
    // 3. 發布
    this.dataService.subject.next(this.inputValue);
  }
}

引入service檔案,在constructor()中注入服務依賴dataService,使用服務中subjectnext()方法發布廣播資料,

創建組件B,用于接收資料,b.component.ts實作代碼如下:

import { Component } from '@angular/core';
// 1. 引入
import { Subscription } from 'rxjs';
import { DataService } from '../data.service';

@Component({
  selector: 'app-b',
  templateUrl: './b.component.html',
})
export class BComponent {
  data: any;

  // 2. subscription
  subscription: Subscription;

  constructor(public dataService: DataService) {
    // 3. 訂閱
    this.subscription = this.dataService.subject.subscribe((data) => {
      this.data = https://www.cnblogs.com/echeverra/archive/2023/03/02/data;
    });
  }

  ngOndestry(): void {
    // 4. 取消訂閱
    this.subscription.unsubscribe();
  }
}

引入Subscription,使用服務中subjectsubscribe()方法創建一個訂閱者,當組件A資料被發布后就可以接收到資料,最后在銷毀時記得取消訂閱,否則會導致泄露,

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

說明:示例中組件AB都引入了同一個服務serviceservice服務則巧妙利用BehaviorSubject實作資料的發布和訂閱,在兩個組件中進行資料的通信,是不是沒有想象的那么難~

路由傳參方式

路由傳參有多種方式,首先我們新建一個路由模塊app-routing.module.ts,代碼如下:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { DetailComponent } from './detail/detail.component';

// 配置路由
const routes: Routes = [
  { path: 'detail', component: DetailComponent },
  { path: 'detail/:id', component: DetailComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

引入路由相關的RouterModuleRoutes,引入跳轉文章詳情組件DetailComponent,配置好路由routes,當路徑為detaildetail/:id時,會加載DetailComponent組件,其中:id為占位符,可以在組件ts檔案中獲取id值,

創建好路由模塊我們還需要在根模塊app.module.ts中匯入,

import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [...],
  imports: [AppRoutingModule],
  providers: [DataService],
  bootstrap: [AppComponent],
})
export class AppModule {}

app.component.html檔案中添加<router-outlet></router-outlet>路由占位符,Angular框架會根據當前的路由器狀態將不同組件動態填充它,

配置完路由準備作業,我們來具體看下有哪些路由傳參方式,

路由路徑傳參

路由路徑中傳參,鏈接形式為:https://ip/detail/1

app.component.html中使用路由指令routerLink的方式在路由路徑中傳參,

<a [routerLink]="['/detail',1]">
1.文章1(路由路徑中傳參,鏈接:https://ip/detail/1)
</a>

detail組件detail.component.ts中使用當前路由物件ActivatedRoute獲取路由傳遞的引數,

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

@Component({
  selector: 'app-detail',
  templateUrl: './detail.component.html',
})
export class DetailComponent implements OnInit {
  id: any;

  constructor(private routeInfo: ActivatedRoute) {}

  ngOnInit() {
    // 獲取路由引數方法
    this.routeInfo.params.subscribe((params: Params) => {
      this.id = params['id'];
    });
  }
}

查詢引數傳參

查詢引數中傳參,鏈接形式為:https://ip/detail?id=2

app.component.html中同樣使用路由指令routerLink,在queryParams查詢引數中傳遞資料,

<a [routerLink]="['/detail']" [queryParams]="{ id: 2 }">
2. 文章2(查詢引數中傳參,鏈接:https://ip/detail?id=2)
</a>

detail組件detail.component.ts中使用當前路由物件ActivatedRoute獲取路由傳遞的引數,

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

@Component({
  selector: 'app-detail',
  templateUrl: './detail.component.html',
})
export class DetailComponent implements OnInit {
  id: any;

  constructor(private routeInfo: ActivatedRoute) {}

  ngOnInit() {
    // 獲取路由引數方法(params改為queryParams)
    this.routeInfo.queryParams.subscribe((params: Params) => {
      this.id = params['id'];
    });
  }
}

仔細觀察會發現,第一種路由路徑中傳參使用的是this.routeInfo.queryParams獲取資料,而第二種查詢引數中傳參使用的是this.routeInfo.queryParams,一定要注意這個區別,

路由配置傳參

除了在app.component.html中使用路由指令routerLink,我們還可以在app.component.ts檔案中通過路由配置中傳參,

app.component.html檔案中系結兩個點擊方法toArticle3()toArticle4()

<a (click)="toArticle3()">
3. 文章3(路由配置中傳參,鏈接:https://ip/detail/3)</a>

<a (click)="toArticle4()">
4. 文章4(路由配置中傳參,鏈接:https://ip/detail?id=4)</a>

app.component.ts檔案中通過路由Routernavigate()方法實作跳轉,

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {

  constructor(private router: Router) {}

  toArticle3() {
    // 路由跳轉文章3
    this.router.navigate(['/detail', 3]);
  }

  toArticle4() {
    // 路由跳轉文章4
    this.router.navigate(['/detail'], { queryParams: { id: 4 } });
  }
}

雖然是通過路由配置傳參跳轉,但我們仍然可以發現,文章3和文章1的跳轉鏈接一致,文章4和文章2的跳轉鏈接一致,本質上也是路由路徑傳參和查詢引數傳參,所以在detail.component.ts中,接收路由引數的方法是一致的,

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

@Component({
  selector: 'app-detail',
  templateUrl: './detail.component.html',
})
export class DetailComponent implements OnInit {
  id: any;

  constructor(private routeInfo: ActivatedRoute) {}

  ngOnInit() {
    // 文章3路由引數獲取(params)
    this.routeInfo.params.subscribe((params: Params) => {
      this.id = params['id'];
    });
  
    // 文章4路由引數獲取(queryParams)
    this.routeInfo.queryParams.subscribe((params: Params) => {
      this.id = params['id'];
    });
  }
}

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

這里需要說明下,在線示例中點擊文章url并未發生改變,這是因為stackblitz工具機制的問題,你可以點擊在線示例界面的Open in New Tab按鈕,在單獨頁面打開可規避該問題,

延伸:示例中的獲取路由引數都是使用subscribe引數訂閱的方式,還有一種snapshot引數快照的方式,如獲取文章1路由引數寫法為:this.id = this.routeInfo.snapshot.params['id'];,獲取文章2路由引數寫法為:this.id = this.routeInfo.snapshot.queryParams['id'];,可以看到同樣是paramsqueryParams的區別,

snapshot引數快照和subscribe引數訂閱兩者的區別在于,當路由地址不變的情況下,若引數變化,snapshot引數快斬訓取的引數值不變,subscribe引數訂閱獲取的引數值會變化,

我們使用snapshot引數快照測驗一下文章1和文章3,效果如下:

那么snapshot引數快斬訓取的引數為什么不發生變化了呢?這是由于第一次點擊文章1跳轉detail組件,constructor()ngOnInit()會被呼叫一次,再次點擊文章3,由于detail組件頁面已經被創建了,ngOnInit()方法不會再次被呼叫,所以路由引數id依然保存著第一次被創建時候的值1

LocalStorage方式

當然你也可以使用本地存盤這種比較通用的方式在組件間通信,

創建C組件c.component.ts將資料存盤到keycValuelocalStorage中,代碼如下:

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

@Component({
  selector: 'app-c',
  templateUrl: './c.component.html',
})
export class CComponent {
  constructor() {}

  inputValue: string = '';

  send(): void {
    // 存盤資料
    window.localStorage.setItem('cValue', this.inputValue);
  }
}

創建D組件d.component.ts獲取localStoragecValue的值,

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

@Component({
  selector: 'app-d',
  templateUrl: './d.component.html',
})
export class DComponent {
  data: any;

  constructor() {}

  getValue() {
    // 獲取資料
    this.data = https://www.cnblogs.com/echeverra/archive/2023/03/02/window.localStorage.getItem('cValue');
  }
}

最終展示效果如下,您可以通過 在線示例 預覽效果和編輯除錯:

:這里沒有使用sessionStorage存盤是因為localStorage生命周期是永久的,而sessionStorage生命周期僅為當前標簽頁,如果兩個組件分別在兩個標簽頁,那么使用sessionStorage是無法實作通信的,

服務端通信方式

最后一種通信方式是借助后臺傳輸資料,如A組件調介面發送資料data存盤到后臺,再由B組件調介面獲取資料data,實作資料通信,這里就不做演示了,

總結

Angular組件間的通信方式是多種多樣的,對于不同情景我們可以采用合適的方式進行通信,

本文每個示例的重點我都有詳細的說明,并延展一些相關知識,示例都是我自己一點點親手敲的,從0到1研究示例實作方案,雖然花費了很長時間,但加深鞏固了知識,之前忽略的一些知識細節也得到了補充,建議大家在學習的同時最好也能動手實作,

好啦,以上就是Angular組件間各種通信方式的所有內容,希望對你有所幫助,如有問題可通過我的博客https://echeverra.cn或微信公眾號echeverra聯系我,

你學“廢”了么?

(完)


文章首發于我的博客 https://echeverra.cn/component-communication,原創文章,轉載請注明出處,

歡迎關注我的微信公眾號 echeverra,一起學習進步!不定時會有資源和福利相送哦!


本文來自博客園,作者:echeverra,轉載請注明原文鏈接:https://www.cnblogs.com/echeverra/p/component-communication.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/545618.html

標籤:其他

上一篇:js 運算子 —— 位運算子詳解

下一篇:js高德地圖添加點Marker,添加線段Polyline,添加一個區域Polygon(面)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more