Angular初學者入門第二課——.ts、.d.ts、.state.ts的區別(精品)

初次接觸 Angular 實際項目時,發現里邊有很多不同后綴的文件,雖然沒深入研究過,但根據其他編程語言的經驗猜測這應該是通過后綴名來區分文件的作用。后來有時間研究了一下具體的細節和不同點,就有了今天這篇文章,這些知識雖然基礎但屬于必知必會的內容,希望有需要的看官可以認真讀下去。

一、普通 .ts 文件

  • 普通的 .ts 文件是 TypeScript 源文件,主要用于編寫程序的邏輯和功能,這些文件會被編譯成JavaScript 文件,并在運行時執行
  • 包含實現代碼:普通的 .ts 文件通常包含類、函數、變量的定義和實現邏輯
  • 會被編譯:在構建或編譯項目時,.ts 文件會被 TypeScript 編譯器轉換成 .js 文件
  • 使用場景:組件、服務、模塊、指令等功能性代碼文件
  • 這里把 .component.ts、.module.ts 都作為普通 .ts,app.component.ts 改名為 app-component.ts、app.module.ts 改名為?
    app-module.ts 后
    項目仍可以正常運行(我們一般不改它們的后綴名)
// app.component.ts
import { Component } from '@angular/core';@Component({selector: 'app-root',template: `<h1>Hello Angular!</h1>`,
})
export class AppComponent {title: string = 'Angular App';constructor() {console.log('AppComponent initialized');}
}

二、.d.ts 文件

  • .d.ts 文件是 TypeScript 的類型聲明文件,用于提供類型定義信息,注意不包括具體的實現
  • 它為 TypeScript 編譯器提供類型檢查和代碼補全的支持,主要用于定義模塊、庫、全局變量或接口的類型
  • 僅包含類型聲明:.d.ts 文件只包含類型信息,沒有實現邏輯
  • 不會被編譯:TypeScript 編譯器會直接使用 .d.ts 文件中的類型信息進行類型檢查,但不會將他們編譯成 JavaScript 文件
  • 使用場景:定義全局變量或接口;
    為沒有類型定義的第三方庫提供類型支持;
    為模塊或庫的外部用戶提供類型支持;
  • 通俗點理解?.d.ts 文件中存放需要用 declare 聲明的類型,global.d.ts 改成?globald.ts 編譯會失敗
//以下是 global.d.ts 文件的內容
declare global {interface Window {myCustomProperty: string;}
}//注意:TypeScript 聲明文件必須包含至少一個 export 或 import,否則它會被視為一個全局腳本文件,而不是模塊。
export {};
@Component({selector: 'app-resource',standalone: true,imports: [ CommonModule ],templateUrl: './resource.component.html',styleUrls: ['./resource.component.less']
})
export class ResourceComponent implements OnInit {constructor() { // 使用擴展的字段window.myCustomProperty = 'Hello, window.myCustomProperty!';console.log(window.myCustomProperty);}
}

三、.state.ts

  • .state.ts 文件并不是 TypeScript 本身的標準文件類型,而是通常作為項目中的一種約定,用于定義和管理狀態(state)相關的代碼
  • 它通常用于描述應用程序的狀態模型,或者與狀態管理工具(如NgRx、Akita、Redux等)配合
  • 包含狀態定義和邏輯:.state.ts 文件可能包含狀態模型、初始狀態、狀態操作和選擇器等
  • 會被編譯:與普通的 .ts 文件一樣,.state.ts 文件也會被編譯為 JavaScript 文件
  • 使用場景:通常用于 Angular 項目中的狀態管理模塊,幫助管理局部或全局狀態
  • 既然是非標準文件類型,那么?resource.actions.ts 改名為?resource-actions.ts、resource.model.ts 改名為 resource-model.ts、resource.state.ts 改名為 resource-state.ts 后項目仍可以正常運行(我們一般不改它們的后綴名)
  • 下面的代碼是一個前后端完整的 ResourceState 實例,包括:定義ResourceState、@Selector()、@Action(xxx),以及使用ResourceState 和調用 @Action(xxx)
//resource.model.ts 文件的內容
export interface Resource {id: number,name: string
}export interface ResourceStateModel {resources: Resource[];selectedResourceId: number | null;
}
//resource.actions.ts 文件的內容
import { Resource } from "./resource.model";export class AddResource {static readonly type = '[Resource] Add Resource'; //動作類型constructor(public payload: Resource) {} //傳遞完整的資源數據
}export class SelectResource {static readonly type = '[Resource] Select Resource'; //動作類型constructor(public payload: number) {} //傳遞選中資源的Id
}
//resource.state.ts 文件的內容
import { Injectable } from '@angular/core';
import { State, Action, StateContext, Selector, NgxsAfterBootstrap } from '@ngxs/store';
import { Resource, ResourceStateModel } from './resource.model';
import { AddResource, SelectResource } from './resource.actions';@State<ResourceStateModel>({name: 'resource', //狀態的名稱,用于標識defaults: {resources: [{id: 1,name: 'name01'},{id: 2,name: 'name02'}], //初始資源列表為空,若ngxsAfterBootstrap()中對resources重新賦值則此處的初始化數據無效,若ngxsAfterBootstrap()中沒對resources重新賦值則此處的初始化數據有效selectedResourceId: 1  //初始沒有選中的資源}
})@Injectable({providedIn: 'root'
})
export class ResourceState implements NgxsAfterBootstrap{//定義選擇器,用于從狀態中派生數據//選擇所有資源@Selector()static getAllResources(state: ResourceStateModel): Resource[] {return state.resources;}//選擇當前選中的資源@Selector()static getSelectedResource(state: ResourceStateModel): Resource | undefined {return state.resources.find(resource => resource.id === state.selectedResourceId);}//定義動作處理器,用于更新狀態,@Action(AddResource)與第二個參數必須是同類型//動作:添加資源@Action(AddResource)addResource(ctx: StateContext<ResourceStateModel>, action: AddResource): void {console.log(`In addResource, action as below:`)console.log(action)const state = ctx.getState();/*...是擴展運算符或剩余參數,擴展運算符用于將數組或對象的元素展開為單獨的值,通常用于合并數組、克隆對象等操作。示例 1:展開數組const array1 = [1, 2, 3];const array2 = [4, 5, 6];const combinedArray = [...array1, ...array2];console.log(combinedArray); // 輸出:[1, 2, 3, 4, 5, 6]示例 2:展開對象const obj1 = { name: 'Alice', age: 25 };const obj2 = { location: 'New York' };const combinedObj = { ...obj1, ...obj2 };console.log(combinedObj); // 輸出:{ name: 'Alice', age: 25, location: 'New York' }*///這兩行的效果一樣,展開之后又組裝成對象console.log(state)console.log({...state})console.log(state.resources)console.log(...state.resources)console.log({...state.resources})const newResources = [...state.resources, action.payload];ctx.setState({...state,resources: newResources});}//動作:選擇資源@Action(SelectResource)selectResource(ctx: StateContext<ResourceStateModel>, action: SelectResource): void {console.log(`In selectResource, action as below:`)console.log(action)const state = ctx.getState();ctx.setState({...state,selectedResourceId: action.payload});}public ngxsAfterBootstrap(ctx: StateContext<ResourceStateModel>): void {console.log('check bootstrap')//ctx.patchState({resources: [{id: 1, name: "test",}]})}
}
<!-- resource.component.html 文件的內容 -->
<ul><!-- @State支持@Selector()讀取狀態值、@Action()更新狀態值,這些功能普通Service也能實現@State最核心的Angular 提供的 AsyncPipe 是管理 Observable 最簡單和推薦的方式。它會自動訂閱和取消訂閱,無需手動管理。如果手動對普通Service實現訂閱和取消訂閱還是比較復雜的--><li *ngFor="let resource of resources$ | async" (click)="onSelectResource(resource.id)">{{resource.name}}<span *ngIf="(selectedResource$ | async)?.id === resource.id">(selected)</span></li> 
</ul>
<button (click)="addResource()">Add Resource</button> 
//resource.component.ts 文件的內容
import { Component, inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AddResource, SelectResource } from '../../models/resource.actions';
import { Resource } from '../../models/resource.model';
import { Observable } from 'rxjs';
import { ResourceState } from '../../models/resource.state';
import { Store } from '@ngxs/store';@Component({selector: 'app-resource',standalone: true,imports: [ CommonModule ],templateUrl: './resource.component.html',styleUrls: ['./resource.component.less']
})
export class ResourceComponent implements OnInit {//使用 @Select 裝飾器獲取狀態的選擇器值public readonly resources$: Observable<Resource[]> = inject(Store).select(ResourceState.getAllResources);public readonly selectedResource$: Observable<Resource | undefined>= inject(Store).select(ResourceState.getSelectedResource);constructor(private store: Store) { }ngOnInit() {}ngAfterViewInit(): void {//Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.//Add 'implements AfterViewInit' to the class.}addResource(): void {const newResource: Resource = {id: Math.floor(Math.random() * 1000), //隨機生成Idname: `Resource ${Math.floor(Math.random() * 100)}`};//觸發 AddResource 動作,找到resource.state.ts中的@Action(AddResource),向狀態中添加新資源this.store.dispatch(new AddResource(newResource));}onSelectResource(resourceId: number): void {//觸發 SelectResource 動作,找到resource.state.ts中的@Action(SelectResource)更新選中的資源Idthis.store.dispatch(new SelectResource(resourceId));}
}

四、總結

討論了這么多,文章中列舉出的這些不同后綴名的文件,只有 .d.ts 文件的后綴名不能改,其他后綴名改完之后項目仍然能正常運行,但是 Angular 的這一設定跟 .Net 中的 Controller 類似,約定大于配置,所有的開發者都按照相同的規則進行開發,這樣當你讀其他人的代碼時就能快速入手,確實對大家都是好事。

OK,如果各位看官覺得本文對你有所幫助,請點贊、收藏、評論支持一下,我將感激不盡。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92569.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92569.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92569.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

進程狀態+進程優先級+進程上下文切換解讀

一、進程狀態 什么是進程狀態&#xff1f;進程狀態指的是在操作系統中進程在生命周期中所處的不同階段。進程狀態有哪些呢&#xff1f;我們可以看到上述圖片 進程狀態分為&#xff1a;創建狀態、就緒狀態、運行狀態、阻塞狀態和終止狀態所有的操作系統在實現進程狀態變化的時候…

Android 原生與 Flutter 通信完整實現 (Kotlin 版)

1. 項目配置 pubspec.yaml 添加依賴 dependencies:flutter:sdk: flutterprovider: ^6.0.52. Flutter 端實現 狀態管理類 // settings_provider.dart import package:flutter/foundation.dart;class SettingsProvider with ChangeNotifier {String _themeColor blue;bool _dark…

數字圖像處理3

圖像線性濾波——目的就是濾去噪聲&#xff0c;但是邊緣會模糊&#xff0c;整體也模糊線性&#xff1a;鄰域平均法&#xff08;4鄰域平均和8鄰域平均&#xff09;用當前運算點所在鄰域的平均值來代替該點的平均值im_for_read"D:\AAAproject\PYproject\EXPERuse\zaosheng.j…

Linux發行版分類與Centos替代品

讓centos7氣的不輕&#xff0c;這玩意兒太老了&#xff0c;什么都不好配置。 目錄Linux 發行版的大致分類1. Red Hat 系列&#xff08;RPM 系&#xff09;2. Debian 系列&#xff08;DEB 系&#xff09;3. Arch 系列4. SUSE 系列CentOS 7 的替代品推薦AlmaLinux 和 Rocky Linux…

大語言模型提示工程與應用:大語言模型對抗性提示安全防御指南

對抗性提示工程 學習目標 理解大語言模型中對抗性提示的風險與防御機制&#xff0c;掌握提示注入、提示泄露和越獄攻擊的檢測方法&#xff0c;培養安全防護意識。 相關知識點 對抗性攻擊類型防御技術 學習內容 1 對抗性攻擊類型 1.1 提示注入 提示注入旨在通過使用巧妙…

避不開的數據拷貝(2)

接著上周未完的話題 避不開的數據拷貝。 既然處理器是通用機器&#xff0c;就沒有專屬數據&#xff0c;所以數據都要從別處調來&#xff0c;這就涉及到了數據搬運&#xff0c;就有了外設的概念。由于不同外設和處理器一起共享數據存儲&#xff0c;時間會花在兩方面&#xff1a…

娃哈哈經銷商“大洗牌”:砍掉年銷300萬以下經銷商

文 | 大力財經據第一財經報道&#xff0c;娃哈哈在宗馥莉“鐵腕”策略推動下&#xff0c;正經歷經銷商體系的重大變革&#xff0c;陸續砍掉年銷低于300萬元的經銷商&#xff0c;方式有時頗為激進&#xff0c;“一刀切”的做法引發諸多爭議&#xff0c;部分經銷商反饋存在款項未…

drippingblues靶機通關練習筆記

前言 將靶機導入到vmware虛擬機上 靶機下載地址&#xff1a;https://download.vulnhub.com/drippingblues/drippingblues.ova 將網段都設置為nat 信息收集 ip端口掃描 netdiscover -r 192.168.25.1/24 --確定ip nmap -A -p- 192.168.25. kalid的ip&#xff1a;1…

QT第三講- 機制、宏、類庫模塊

文章目錄 ?? 一、Qt核心機制與類庫 ?? 1. 元對象系統(Meta-Object System) ? 2. 信號與槽(Signals & Slots) ? 通信機制 ?? 3. 屬性系統(Property System) 動態屬性 例程 類的附加信息 Q_CLASSINFO 例程 ?? 二、全局定義與容器 ?? 1. 全局數據類型與函數…

(LeetCode 每日一題) 869. 重新排序得到 2 的冪 (哈希表+枚舉)

題目&#xff1a;869. 重新排序得到 2 的冪 思路&#xff1a;哈希表枚舉。先預處理出所有的2的冪數&#xff0c;用哈希表來存儲。 C版本&#xff1a; class Solution { public:// 哈希表存儲所有 2的冪數 按升序排列的形式unordered_set<string> st;// 預處理出所有的2…

WebAssembly技術詳解:從瀏覽器到云原生的高性能革命

引言&#xff1a;WebAssembly的誕生與使命 2015年&#xff0c;當Mozilla、Google、Microsoft和Apple四大瀏覽器廠商聯合發布WebAssembly&#xff08;Wasm&#xff09;技術預覽時&#xff0c;業界尚未意識到這將開啟Web性能的新紀元。作為繼HTML、CSS、JavaScript之后的第四種We…

性能解析案例

異步io是內核fd與應用程序直接的關系io 多路復用1.檢測io是否就緒2.read/write消息隊列kafka&#xff1a;1.典型應用 &#xff1a;異步處理&#xff0c;系統解耦&#xff0c;流量削峰&#xff0c;日志處理2.核心原理&#xff1a;kafka體系結構以及讀寫流程3.具體操作&#xff1…

青龍峽拔韭菜

我們一年四季&#xff0c;除了冬天不往山里進&#xff0c;其余季節&#xff0c;只要天氣允許&#xff0c;我們都會進山。在山里拔韭菜&#xff0c;是我們百做不煩的一件事。今年大旱&#xff0c;從五月份上山找韭菜&#xff0c;沒有如愿。直到入秋后&#xff0c;我們再次去青龍…

5、docker鏡像管理命令

1、命令總覽命令&#xff08;含關鍵參數&#xff09;作用出現頻率備注docker buildx build --platform … -t … --push .一次構建并推送多平臺鏡像高頻需先 docker buildx create --usedocker buildx build -o typedocker,destxxx.tar .構建后離線導出 tar 包中頻只導出單平臺…

阿里云ECS云服務器臨時升級帶寬方法

阿里云ECS云服務器臨時升級帶寬方法一、背景與需求二、原理三、操作步驟步驟 0: 準備工作步驟 1: 創建彈性網卡 (ENI)步驟 2: 創建并綁定彈性公網IP (EIP)步驟 3: SSH登錄ECS并切換到高速通道 (eth1)步驟 4: 執行你的高帶寬任務步驟 5: 任務完成&#xff0c;切回默認網卡 (eth0…

Java語言簡介

一.Java語言的起源 Java語言的前身是Oka語言,是美國Sun Microsystems公司于1991年推出的,僅限于公司內部使用的語言。1995年,Sun公司將Oak語言更名為Java語言,并正式向公眾推出。這之后,Java語言不斷更新,其類庫越來越豐富,性能逐步提升,應用領域也顯著拓展,已成為當今…

VUE+SPRINGBOOT從0-1打造前后端-前后臺系統-視頻列表與視頻播放

在現代Web開發中&#xff0c;視頻播放功能已成為許多網站的基本需求。本文將基于Vue.js框架&#xff0c;詳細講解如何實現一個視頻列表與播放器交互的功能模塊。這個組件可以讓用戶點擊列表中的視頻項來播放對應的視頻&#xff0c;并支持再次點擊關閉播放器。功能概述我們實現的…

詳解 Seaborn:讓數據可視化更簡單高效的 Python 庫

在數據科學領域&#xff0c;可視化是理解數據、挖掘規律的重要手段。今天要為大家介紹的 Seaborn 庫&#xff0c;正是數據可視化領域的一把 “利器”。它基于 Matplotlib 開發&#xff0c;卻憑借更簡潔的接口和更美觀的默認樣式&#xff0c;成為眾多數據分析師的首選工具。下面…

Cesium1.95中如何高效管理 1500 個高頻實體

一、建議&#xff1a;不要頻繁創建/銷毀&#xff0c;而是復用對象&#xff1b;????使用 CallbackProperty更新位置而不是刪了重建&#xff1b;????對大量 Billboard / Polyline / Label&#xff0c;優先使用對應的 *Collection&#xff0c;然后批量更新&#xff1b;??…

全面了解機器語言之kmeans

深入理解 KMeans 聚類算法&#xff1a;原理、實現與應用在機器學習領域&#xff0c;聚類算法作為無監督學習的核心技術之一&#xff0c;一直以來都是數據挖掘和模式識別的重要工具。其中&#xff0c;KMeans 算法以其簡潔的原理、高效的計算性能和廣泛的適用性&#xff0c;成為最…