前提:
1. 視頻鏈接:
2. 文件鏈接:
3. 官網(wǎng):
一乳乌、簡介
google研發(fā)巷嚣,為了面向大型復雜的項目捌木,使用javascript可以搭建
ts 是 javascript 的超集挎挖,包含 es6 和 es5
實現(xiàn)類似 java | c# 這種面向對象的編程語言
ts 是由 c# 之父 Anders Hejlsberg 發(fā)起的
建議使用 es6 語法
二尔破、使用
1. 安裝
npm|cnpm install -g typescript
或者
yarn global add typescript
安裝成功如下圖:
2. 使用
創(chuàng)建文件 hello.ts
寫入ts語法ts 編譯成 es5 語法
瀏覽器本身不支持ts語法
命令:tsc hello.ts
注意:每次運行都需要編譯-
配置自動化編譯腳本
- 創(chuàng)建 tsconfig.json 文件
tsc --init
生成配置文件 - 快捷鍵 Ctrl+shift+B 選擇監(jiān)視模式 進行編譯
每次有更新就會編譯
tsc watch 是自動監(jiān)聽肄梨,下次保存文件就自動編譯
tsc build 是編譯一次 - 創(chuàng)建 tsconfig.json 文件
三.語法
以下 typescript 簡寫為 ts
1.數(shù)據(jù)類型
ts 中 為了 使代碼更規(guī)范,更有利于維護闻丑,增加了類型校驗
變量一旦確定為哪個數(shù)據(jù)類型漩怎,不可改變數(shù)據(jù)類型
函數(shù)返回值類型等等語法比較嚴格,不然語法會報錯
序號 | 類型 | 標識符 | 含義 | 備注 | 是否基本類型 |
---|---|---|---|---|---|
1 | 布爾類型 | boolean | [true/false] | let flag:boolean=false |
√ |
2 | 數(shù)字類型 | number | [\d+.\d+] | 未區(qū)分浮點類型和整數(shù)類型 | √ |
3 | 字符串類型 | string | [char+] | 單嗦嗡、雙引號包裹 | √ |
4 | 數(shù)組類型 | array | [number...] | 必須指定數(shù)組類型勋锤,如 let arr:number[] = [1,2,3] , 第二種定義方式 let arr:Array<number> = [1,2] 泛型
|
√ |
5 | 元組類型 | tuple | 數(shù)組的一種,可以指定每個數(shù)組元素的類型 | let arr:[string, number, boolean] = ['ts', 3.18, true] |
√ |
6 | 枚舉類型 | enum | 事先考慮某個變量可能取得值 |
enum 枚舉名 { 標識符[=整型常數(shù)], ... } 侥祭,類似C語言,其中值默認為索引值叁执, 示例: enum Flag {success=1, error} let f:Flag=Flag.success
|
√ |
7 | 任意類型 | any | 可以賦值為任意類型 | Object類型可以指定該類型 | × |
8 | null | null | 一個變量可以是基本數(shù)據(jù)類型,或者null或者undefined | let num:number / null |
× |
9 | undefined | undefined | 其他類型未初始化變量為undefined卑硫,但是引用會報錯;如果直接指定undefined沒有初始化就不會報錯 | let num:number / null / undefined |
× |
10 | 空類型 | void | 一般用于方法沒有返回值 | function run():void{} |
× |
11 | never類型 | never | 從來不會出現(xiàn) | let a:never a=(()=>{ throw new Error('錯誤') })() |
× |
2.函數(shù)
- 函數(shù)的定義
· 函數(shù)參數(shù)指定類型蚕断,返回值指定類型- 函數(shù)聲明法
function run(name:string, age:number):void{ }
- 匿名函數(shù)法
· es5 實參和形參無需一樣欢伏,但是ts中必須一樣,如果不一樣需要配置可選參數(shù)亿乳,let fun = function(name:string, age:number):void{ }
? 必須配置到后面硝拧,才能夠不混淆
· es5里面沒法設置默認參數(shù)径筏,ts和es6都可以設置默認參數(shù)let fun = function(name:string, age?:number):void{ // age 可傳可不傳 }
· 剩余參數(shù)[實參數(shù)量>形參數(shù)量]let fun = function(name:string, age:number=20):void{ // age 可傳可不傳,默認為 20 } fun('zhangsan')
... 三點運算符(es6)的使用let fun = function(...result:number[]):void{ // result 為數(shù)組類型使用 } fun(1, 2, 3, 4)
-
函數(shù)重載
java 中方法的重載指的是兩個或兩個以上同名函數(shù)障陶,但它們的參數(shù)不一樣滋恬,這時會出現(xiàn)函數(shù)重載的情況
ts 中重載指的是通過為同一個函數(shù)提供多個函數(shù)類型定義來實現(xiàn)多種功能的目的
ts 需要兼容 es5 和 es6 重載的寫法, 與 java 有區(qū)別function getInfo(str: string): string function getInfo(str: number): number function getInfo(str: any): any { if (typeof str === 'string') { return '我的名字是' + str } else { return '我的年齡是' + str } } console.log(getInfo('張三')) // 我的名字是張三 console.log(getInfo(20)) // 我的年齡是20
箭頭函數(shù) es6
() => {}
this 上下文指向函數(shù)運行的上下文抱究, 非私有
3.類(上) —— es5 中的類
-
Es5中的類和靜態(tài)方法
// 1. 最簡單的類 - 通過構造函數(shù) function Person() { this.name='張三'} var p = new Person() alert(p.name) // 2. 構造函數(shù)和原型鏈增加屬性或者方法 // 區(qū)別: 實例不會共享構造函數(shù)的屬性和方法恢氯, 原型鏈會 function Person() { this.name='張三' this.run = function () { return this.name + '在奔跑' } } Person.prototype.work = function () { return this.name + '在工作' } var p = new Person() alert(p.run) alert(p.work) // 3. 類里面的靜態(tài)方法 // 實例方法必須 new 一個實例才可以使用,靜態(tài)相當于默認就有 Person.getInfo = function () { return '我是靜態(tài)方法' } alert(Person.getInfo())
-
Es5 繼承(原型鏈繼承昆淡、對象冒充繼承仲墨、原型鏈+對象冒充組合繼承)
- 對象冒充繼承
function Person() { this.name='張三' this.run = function () { return this.name + '在奔跑' } } Person.prototype.work = function () { return this.name + '在工作' } var p = new Person() // Web 類 繼承 Person 類 // 1. 對象冒充實現(xiàn)繼承 function Web() { Person.call(this) // 對象冒充實現(xiàn)繼承 } var w = new Web() console.info(w.run()) // 對象冒充可以繼承構造函數(shù)的屬性和方法 // console.info(w.work()) // 但是無法繼承原型鏈上的屬性和方法
- 原型鏈繼承
function Person(name) { this.name = name this.run = function () { return this.name + '' } } Person.prototype.work = function () { return this.name + '在工作' } var p = new Person() // Web 類 繼承 Person 類 // 2. 原型鏈實現(xiàn)繼承 function Web(name) { } Web.prototype = new Person() var w = new Web() console.info(w.run()) // 可以繼承構造函數(shù)的屬性和方法 undefined在奔跑 console.info(w.work()) // 可以繼承原型鏈上的屬性和方法 undefined在工作 // 問題: 實例化子類的時候蜘矢,無法給父類傳參
- 原型鏈+對象冒充組合繼承
function Person(name) { this.name = name this.run = function () { return this.name + '在奔跑' } } Person.prototype.work = function () { return this.name + '在工作' } // 2. 原型鏈+對象冒充組合實現(xiàn)繼承 function Web(name) { Person.call(this, name) } Web.prototype = new Person() // 或者 Web.prototype = Person.prototype var w = new Web('zhangsan') console.info(w.run()) // 可以繼承構造函數(shù)的屬性和方法 console.info(w.work()) // 可以繼承原型鏈上的屬性和方法
4.類(下) —— ts 中的類
-
類的定義
class
關鍵字class Person { name:string; // 屬性,前面省略了 public 關鍵字【默認】 constructor(name:string) { // 構造函數(shù)敢靡,實例化類的時候觸發(fā)的方法 this.name = name } run():void { console.info(`${this.name}在跑步`) } } // 調(diào)用 let p = new Person('小張') p.run()
-
繼承
extends
關鍵字,super
關鍵字// 繼承 Person class worker extends Person { constructor(name:string){ super(name) } // 方法先看子類是否有苦银,然后父類 } let w = new Web('李四') console.log(w.run())
類里面的修飾符 -
public,protected,private
public
: 公有 啸胧, 全都可以訪問【默認】
protected
: 保護 , 類和子類可以訪問
private
: 私有 幔虏, 類可以訪問
-
靜態(tài)屬性或者靜態(tài)方法 -
static
關鍵字class Person{ public name:string; static a:number = 0; constructor(name:string) { this.name = name } run ():void{ console.log(`${this.name}在奔跑`) } static print():void{ // 靜態(tài)方法無法直接調(diào)用類里的屬性 纺念, static語法類似 C 語言 // 當前類里面的全局存在 console.info(`靜態(tài)方法` + this.a++) } } Person.print()
-
抽象類 繼承 多態(tài)
-
多態(tài):父類定義一個方法不去實現(xiàn),讓繼承它的子類去實現(xiàn) 所计, 每個子類根據(jù)自己的特性去定義不同的表現(xiàn)
多態(tài)屬于繼承class Animal { name: string constructor(name: string) { this.name = name } eat() { console.log('吃的方法') } work() { console.log('工作的方法') } } class Dog extends Animal { constructor(name: string) { super(name) } eat() { // this is 多態(tài) return '主人已經(jīng)準備好狗糧柠辞,快來吃飯!' } }
-
抽象方法 - abstract 關鍵字
ts 中的抽象類主胧,是提供其他類繼承的基類/父類叭首,不能直接實例化
abstract
關鍵字來定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現(xiàn)并且必須在派生類中實現(xiàn)
作用: 抽象類和抽象方法用于定義標準// 定義animal子類必須包含eat方法 abstract class animal { // 抽象類 // 可以包含非抽象方法 work() { } abstract eat(): any; // 抽象方法踪栋, 抽象方法只能在抽象類中定義 }
-
5.接口
interface
關鍵字
接口的作用:
在面向對象的編程中焙格,接口是一種規(guī)范的定義
它定義了行為和動作的規(guī)范,起到限制和規(guī)范的作用夷都。
接口定義了某類所需遵守的規(guī)范眷唉,不關注類的內(nèi)部狀態(tài)數(shù)據(jù),也不關注類里面方法的實現(xiàn)細節(jié)囤官,它只規(guī)定類里必須提供某些方法冬阳,提供方法的類就可以滿足實際需要。
ts 中的接口類似于 java, 同時還增加了更靈活的接口類型党饮,包括屬性肝陪、函數(shù)、可索引和類等刑顺。
- 屬性類接口 —— 對 json 的約束
function printLabel(labelInfo: { label: string }):void { // 對傳參 labelInfo 進行了規(guī)定氯窍,必須要有 string類型的 label屬性 } // 對傳入對象的約束 : 屬性接口 interface Label { label: string; // 必須要有 label fontSize?: number; // 可選參數(shù)饲常,可傳可不傳 } // 規(guī)定形參 function print(label:Label):void { // console.info(label.name + label.name) // 語法報錯 // 需要嚴格遵守規(guī)則 } let obj = { name: 1, label: 'hah' } print(obj) // 可以有其他屬性 print({ label: 'jajja' }) // 只能有 label 屬性,否則報錯
-
函數(shù)類型接口 : 對方法傳入的參數(shù) 以及返回值進行 約束
// 加密的函數(shù)類型接口 interface encrypt { (key:string,value:string):string; } let md5: encrypt = function (k: string, v: string): string { return k + v; } console.log(md5('1', '2'))
- 可索引接口 : 數(shù)組狼讨、對象的約束(不常用)
// 對數(shù)組的約束 interface UserArr { [index: number]: string; // 索引值為 string 類型贝淤, index 為索引 } let arr: UserArr = ['aaa', 'bbb'] console.log(arr[0]) // 0 是指 index // 對對象的約束, 可索引接口 interface UserObj { [index: string]: number; // 索引值為 number 類型政供, index 為索引 } let obj1:UserObj = { name: 1, k: 2 } console.log(obj1.name) // name 是指 index
-
類類型接口: 對類的約束 和 抽象類有的相似
implements
關鍵字// 類類型接口: 對類的約束 和 抽象類有點相似 interface Animal2 { name: string; eat(): string; } class Dog1 implements Animal2 { name: string constructor(name: string) { // 構造函數(shù) 初始化 name this.name = name } eat() { return `${this.name}在吃飯` } } let d1 = new Dog1('嘿嘿') console.log(d1.eat())
-
接口擴展: 接口可以繼承接口
關鍵字interface
和extends
的合用// 接口擴展:接口可以繼承接口 interface Animal3 { eat(): void; } interface Person1 extends Animal3 { work(): void; } class Programmer { name: string constructor(name: string) { this.name = name } coding() { return this.name + '在敲代碼中...' } } class Web implements Person1 { eat() {} work() {} } class Web1 extends Programmer implements Person1 { eat() {} work() {} } let web1 = new Web1('zhang') console.info(web1.coding())
6.泛型
泛型: 軟件工程中播聪,我們不僅要創(chuàng)建一致的定義良好的API,同時也要考慮可重用性鲫骗。
組件不僅能夠支持當前的數(shù)據(jù)類型犬耻,同時也能支持未來的數(shù)據(jù)類型,這在創(chuàng)建大型系統(tǒng)時
為你提供了十分靈活的功能执泰。
在 c# 或者 java 等語言中枕磁,可以使用泛型來創(chuàng)建可重用的組件,一個組件可以支持多種類型的數(shù)據(jù)术吝,方便用戶以自己的數(shù)據(jù)類型來使用組件
通俗理解: 泛型就是解決類计济、接口、方法的復用性排苍、對不特定數(shù)據(jù)類型的支持
-
泛型函數(shù)/方法
// 泛型: 傳入類型靈活沦寂, 函數(shù)增強復用性, 拒絕不必要的冗余代碼 function getPerson(name: any): any { // any 類型 return name } getPerson(111) // T(任意字符) 表示類型淘衙,具體由方法調(diào)用的時候決定 function getPerson1<T>(name: T, key: string): any { // any 類型 console.log(name) return name + key } getPerson1<number>(111, 'aa') getPerson1<string>('ahhahah', 'aaa')
-
泛型類:
// 比如有個最小堆算法传藏,需要同時支持返回數(shù)字和字符串兩種類型 class MinClass<T>{ list: T[] = [] add(value: T): void { this.list.push(value) } min(): T { let minNum = this.list[0] for (let i = 0; i < this.list.length; i++) { if (minNum > this.list[i]) { minNum = this.list[i] } } return minNum } } let l1 = new MinClass<string>() l1.add('a') l1.add('b') l1.add('c') console.info(l1.min())
泛類:泛型可以避免重復的代碼以及對不特定的數(shù)據(jù)類型的支持(類型校驗),下面我們把類當做參數(shù)的泛型類
其可以去除重復代碼彤守,可以對類型進行校驗/** * 1. 定義個類 * 2. 把類作為參數(shù)來約束數(shù)據(jù)傳入的類型 */ /** * 需求: * 1. 定義一個 User 的類毯侦,作用是映射數(shù)據(jù)庫字段 * 2. 定義一個 MysqlDb 的類,用于操作數(shù)據(jù)庫 * 3. 把 User 類作為參數(shù)傳入到 MysqlDb 中 * * ` 非常像 java 中的 dto 層 ` */ class User { username: string | undefined; password: string | undefined; } // 操作數(shù)據(jù)庫的泛型類 // 可以去除重復代碼具垫,可以對類型進行校驗 class MysqlDb<T> { list:T[] = [] // 模擬數(shù)據(jù)庫 constructor(l?: T[]) { if (l) { this.list = l } } add(user: T): boolean { this.list.push(user) console.log(user) return true } } var user1 = new User() user1.username = '張三' user1.password = '111' var mysql1 = new MysqlDb<User>() mysql1.add(user1)
NOTES:
- 語法和 java 大差不差 侈离, 都是為了面向對象進行服務
- 這種復用性又讓我想起了原生es5,原型鏈方法
-
泛型接口
interface ConfigFn{ <T>(value: T, key: string): T; } let getData: ConfigFn = function <T>(value: T, k: string): T { console.log(value + k) return value } getData<string>('hahha', 'hhah')
7. ts 中的類型筝蚕、接口卦碾、類、泛型的綜合使用案例 —— ts 封裝統(tǒng)一操作 Mysql 起宽、 Mongodb 洲胖、 Mssql 的底層庫
需求分析如下:
功能:定義一個操作數(shù)據(jù)庫的庫, 支持 Mysql Mssql Mongodb
要求1:Mysql Mssql Mongodb 功能一樣坯沪, 都有 增刪改查(add,update,delet,get)方法
注意:約束統(tǒng)一的規(guī)范绿映,以及代碼重用
解決方案:需要約束規(guī)范所以要定義接口,需要代碼重用所以用到泛型
1. 接口: 在面向對象的過程中屏箍,接口是一種規(guī)范的定義绘梦,它定義了行為和動作的規(guī)范
2. 泛型: 通俗理解,泛型就是提高 類赴魁、接口卸奉、方法的復用性
interface DBI<T>{
add(info: T): boolean;
update(info: T, id: number): boolean;
delete(id: number): boolean;
get(id: number): any[];
}
// 定義一個操作 mysql 數(shù)據(jù)庫的類 tip: 實現(xiàn)泛型接口 類也要是泛型類
class MySqlDb<T> implements DBI<T>{
add(info: T): boolean {
throw new Error("Method not implemented.");
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}
}
class MsSqlDb<T> implements DBI<T>{
add(info: T): boolean {
throw new Error("Method not implemented.");
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}
}
class MongoDb<T> implements DBI<T>{
add(info: T): boolean {
throw new Error("Method not implemented.");
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}
}
// 操作用戶表 定義一個 User 類和數(shù)據(jù)表做映射
class User {
id: number | undefined;
username: string | undefined;
password: string | undefined;
constructor(id: number, username: string, password: string) {
this.id = id
this.username = username
this.password = password
}
}
let u1 = new User(1, 'lily', '111111')
// let mMysql = new MySqlDb() // 沒有校驗作用
let mMySql = new MySqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型
mMySql.add(u1)
let mMsSql = new MsSqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型
mMsSql.add(u1)
8. ts 模塊
js 模塊化 學習
ts 模塊的概念(官方):
· ts1.5發(fā)生了一些術語的變化,‘內(nèi)部模塊’ 稱為 ‘命名空間’
· ‘外部模塊’現(xiàn)在簡稱為‘模塊’颖御,模塊在其自身的作用域里執(zhí)行榄棵,而不是在全局作用域里,說明在一個模塊里的變量潘拱、函數(shù)疹鳄、類等等在模塊外部不可見(不暴露、封裝性) 芦岂,除非 export
瘪弓, 需要使用的時候使用 import
引入 export
暴露的方法、類禽最、變量等等腺怯。
語法與 es6 相同
``` typescript
// index.ts 使用
import {User, UserModel} from './7-ts-modules/model/User'
import {Article, ArticleModel} from './7-ts-modules/model/Article'
/**
* 案例 之 7-ts 進行模塊化
*/
var u = new User(1, 'lily', '111111')
UserModel.add(u)
var article = new Article(1, '特大新聞!特大新聞川无!今天有毛毛雨呛占!', 'lily')
ArticleModel.add(article)
// db.ts
interface DBI<T>{
add(info: T): boolean;
update(info: T, id: number): boolean;
delete(id: number): boolean;
get(id: number): any[];
}
// 定義一個操作 mysql 數(shù)據(jù)庫的類 tip: 實現(xiàn)泛型接口 類也要是泛型類
export class MySqlDb<T> implements DBI<T>{
add(info: T): boolean {
console.info(info)
return true
}
update(info: T, id: number): boolean {
return true
}
delete(id: number): boolean {
return true
}
get(id: number): any[] {
return []
}
}
export class MsSqlDb<T> implements DBI<T>{
add(info: T): boolean {
console.log(info)
return true
}
update(info: T, id: number): boolean {
return true
}
delete(id: number): boolean {
return true
}
get(id: number): any[] {
return []
}
}
// User.ts
import {MySqlDb} from '../db/db'
class User {
id: number | undefined;
username: string | undefined;
password: string | undefined;
constructor(id: number, username: string, password: string) {
this.id = id
this.username = username
this.password = password
}
}
let UserModel = new MySqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型
export { User, UserModel }
// 同理 > Article.ts
import {MsSqlDb} from '../db/db'
class Article {
id: number | undefined;
title: string | undefined;
author: string | undefined;
constructor(id: number, title: string, author: string) {
this.id = id
this.title = title
this.author = author
}
}
let ArticleModel = new MsSqlDb<Article>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型
export { Article, ArticleModel }
```
引入其他模塊之后,編譯之后的文件路徑會有所變化
Notes:
- 可以感受到 ts 不僅可以用于 網(wǎng)頁懦趋, 還可以用于 大型程序多人開發(fā)晾虑, nodejs環(huán)境...
- 其編程思想仍然更古不變,編程思想仅叫,設計模式很重要
9. 命名空間
定義:
代碼量較大的情況下帜篇,為了避免各種變量命名相沖突,可將相似功能的函數(shù)惑芭、類坠狡、接口等放置到命名空間內(nèi)
同 java 的包、.Net 的命名空間一樣遂跟, ts 的命名空間可以將代碼包裹起來逃沿,只對外暴露需要在外部訪問的對象。
命名空間內(nèi)的對象通過 export
暴露
與模塊的區(qū)別:
名稱 | 區(qū)分 |
---|---|
命名空間 | 內(nèi)部模塊幻锁,主要用于組織代碼凯亮,避免命名沖突 |
模塊 | ts 的外部模塊簡稱,側重代碼的復用哄尔,一個模塊里可能會有多個命名空間 |
相同點: 解決的都是代碼作用域的問題
利用 namespace
關鍵字:
``` typescript
namespace PersonA {
interface Animal {
name: string;
eat() : void;
}
export class Dog implements Animal {
name: string;
constructor(name:string) {
this.name = name
}
eat() {
console.log('小狗在吃飯')
}
export namespace H {
let name: string = 'jaj'
}
}
}
namespace PersonB {
}
let dog = new PersonA.Dog('花花')
dog.eat()
```
10. 裝飾器
定義:
裝飾器是一種特殊類型的聲明假消,它能夠被附加到類聲明、方法岭接、屬性或參數(shù)上富拗,可以修改類的行為臼予。
通俗理解: 裝飾器是一個方法,可以注入到類啃沪、方法粘拾、屬性參數(shù)來擴展他們的功能。
常見的裝飾器有: 類裝飾器创千、屬性裝飾器缰雇、方法裝飾器、參數(shù)裝飾器
裝飾器的寫法: 普通裝飾器(無法傳參)追驴、裝飾器工廠(可傳參)
裝飾器是過去幾年中 js 最大的成就之一械哟,已經(jīng)是 es7 的標準特性之一
-
類裝飾器: 在類聲明之前被聲明(緊靠著聲明)。
類裝飾器應用于類構造函數(shù)殿雪,可以用來監(jiān)視暇咆、修改、替換類定義丙曙,傳入一個參數(shù)
es6 也有裝飾器 decorator{}- 普通方法(無法傳參)
function logClass(params: any) { console.info(params) // 當前的類 params.url = 'hahha' params.prototype.Url = 'XXXX' params.prototype.run = function (): void { console.info('running....') } } @logClass class HttpClient1 { constructor() { } getData() { } } var http: any = new HttpClient1() console.log(http.url) // 無法獲取糯崎, undefined console.log(http.Url) http.run()
- 裝飾器工廠(可傳參)
// 2. 類裝飾器:裝飾器工廠(可傳參) namespace class2 { function logClass(params: string) { return function (target: any) { console.log(target) // 當前的類 console.info(params) // 裝飾器傳入?yún)?shù) target.prototype.url = params target.prototype.run = function (): void { console.info('running....') } } } @logClass('http://xxx.com/api') class HttpClient1 { constructor() { } getData() { } } var http: any = new HttpClient1() console.log(http.url) http.run() }
- 類裝飾器替換類的構造函數(shù)
function logClass(target: any) { return class extends target () { // 相當于重寫,因為每個屬性都需要 extends constructor() { } getData() { } } } @logClass class HttpClient1 { constructor() { } getData() { } }
-
屬性裝飾器
都是語法糖function logClass (params: any){ return function (target: any, attr: any) { console.log(target) // 類 console.log(attr) // url target[attr] = params } } // @logClass('http://itying.com') // var url: any | undefined; // 無效 class ht1 { @logClass('http://itying.com') public url: any | undefined; } var t = new ht1() console.log(t.url)
-
方法裝飾器
方法裝飾器在運行時傳入下列 3 個參數(shù):- 對于靜態(tài)成員來說是類的構造函數(shù)河泳,對于實例成員是類的原型對象
- 成員的名字
- 成員的屬性描述符
跟 es6 的相似
// 方法裝飾器 function get(params: any) { return function (target: any, methodName: any, desc: any) { // console.log(target) // 對于靜態(tài)成員來說是類的構造函數(shù)沃呢,對于實例成員是類的原型對象 // console.log(methodName) // 成員的名字 // console.log(desc) // 成員的屬性描述符 // 修改裝飾器的方法, 把裝飾器方法里面?zhèn)魅氲乃袇?shù)改為 string 類型 // 1. 保存當前的方法 let oMethod = desc.value // 保存當前方法 // 修改當前方法 desc.value = function (...args: any[]) { args = args.map((val) { return String(val) }) console.log('裝飾器中轉換的形參:' , args) oMethod.apply(this, args) // 融合類中的 該方法語句 } } } class Ht { url: string | undefined; constructor() { } @get('http://www.itying.com') getData(...args:any[]) { console.log(args) console.log('我是類中的方法') } } let ht = new Ht() ht.getData(12, 11, true)
-
參數(shù)裝飾器
不常用拆挥, 其他裝飾器也可以實現(xiàn)// 方法參數(shù)裝飾器 function logParams(params: any) { return function (target: any, methodName: any, paramsIndex: any) { console.log(target) console.log(methodName) console.log(paramsIndex) target.url = params } } class Ht { url: string | undefined; constructor() { } getCan(@logParams('uuid') uuid: any) { console.log(uuid) console.log('我是類中的參數(shù)方法') } } let ht = new Ht() ht.getCan('jjj') console.log(ht.url)
裝飾器順序:
順序 | 名稱 | 多個內(nèi)部順序 |
---|---|---|
1 | 屬性裝飾器 | |
2 | 方法裝飾器 | |
3 | 方法參數(shù)裝飾器 | 先執(zhí)行后面的薄霜,從后向前 |
4 | 類裝飾器 | 先執(zhí)行后面的,從后向前 |
四.案例 【 ts + angular 】
前提:
安裝angular/cli:
npm|cnpm install -g @angular/cli
驗證:
ng version
新建項目:
ng new demo01
scss 和 sass 的區(qū)別:scss是sass的一個升級版本纸兔,完全兼容sass之前的功能惰瓜,又有了些新增能力
- 文件擴展名不同,sass是以“.sass”后綴為擴展名汉矿,而SCSS是以“.scss”后綴為擴展名崎坊。
- 語法不同,sass是以嚴格的縮進式語法規(guī)則來書寫洲拇,而scss的語法與css語法非常相似奈揍。
運行項目:
ng serve --open
來自b站視頻觀看筆記,有錯請指正8承男翰!