国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

typeScript中的類型斷言和類型別名、字符串字面量類型

這篇具有很好參考價(jià)值的文章主要介紹了typeScript中的類型斷言和類型別名、字符串字面量類型。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

1.類型斷言

語(yǔ)法

?2.類型斷言的用途

2.1?將一個(gè)聯(lián)合類型斷言為其中一個(gè)類型?

?2.2 將一個(gè)父類斷言為更加具體的子類

?2.3?將任何一個(gè)類型斷言為?any

2.4?將?any?斷言為一個(gè)具體的類型

類型斷言的限制

雙重?cái)嘌?/p>

類型斷言 vs 類型轉(zhuǎn)換

類型斷言 vs 類型聲明

類型斷言 vs 泛型


1.類型斷言

類型斷言(Type Assertion)可以用來(lái)手動(dòng)指定一個(gè)值的類型。一般運(yùn)用在聯(lián)合類型里面。

語(yǔ)法

值? as? 類型

或者

<類型>值

在 tsx 語(yǔ)法(React 的 jsx 語(yǔ)法的 ts 版)中必須使用前者,即?值 as 類型。

形如?<Foo>?的語(yǔ)法在 tsx 中表示的是一個(gè)?ReactNode,在 ts 中除了表示類型斷言之外,也可能是表示一個(gè)泛型。

故建議大家在使用類型斷言時(shí),統(tǒng)一使用?值 as 類型?這樣的語(yǔ)法,本書(shū)中也會(huì)貫徹這一思想。

?2.類型斷言的用途

2.1?將一個(gè)聯(lián)合類型斷言為其中一個(gè)類型?

當(dāng) TypeScript 不確定一個(gè)聯(lián)合類型的變量到底是哪個(gè)類型的時(shí)候,我們只能訪問(wèn)此聯(lián)合類型的所有類型中共有的屬性或方法

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function getName(animal: Cat | Fish) {
    return animal.name;
}

?而有時(shí)候,我們確實(shí)需要在還不確定類型的時(shí)候就訪問(wèn)其中一個(gè)類型特有的屬性或方法,比如:

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function isFish(animal: Cat | Fish) {
    if (typeof animal.swim === 'function') {
        return true;
    }
    return false;
}

// index.ts:11:23 - error TS2339: Property 'swim' does not exist on type 'Cat | Fish'.
//   Property 'swim' does not exist on type 'Cat'.

上面的例子中,獲取?animal.swim?的時(shí)候會(huì)報(bào)錯(cuò)。

此時(shí)可以使用類型斷言,將?animal?斷言成?Fish

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function isFish(animal: Cat | Fish) {
    if (typeof (animal as Fish).swim === 'function') {
        return true;
    }
    return false;
}

?這樣就可以解決訪問(wèn)?animal.swim?時(shí)報(bào)錯(cuò)的問(wèn)題了。

需要注意的是,類型斷言只能夠「欺騙」TypeScript 編譯器,無(wú)法避免運(yùn)行時(shí)的錯(cuò)誤,反而濫用類型斷言可能會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤:

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function swim(animal: Cat | Fish) {
    (animal as Fish).swim();
}

const tom: Cat = {
    name: 'Tom',
    run() { console.log('run') }
};
swim(tom);
// Uncaught TypeError: animal.swim is not a function`

上面的例子編譯時(shí)不會(huì)報(bào)錯(cuò),但在運(yùn)行時(shí)會(huì)報(bào)錯(cuò):

Uncaught TypeError: animal.swim is not a function~?

原因是?(animal as Fish).swim()?這段代碼隱藏了?animal?可能為?Cat?的情況,將?animal?直接斷言為?Fish?了,而 TypeScript 編譯器信任了我們的斷言,故在調(diào)用?swim()?時(shí)沒(méi)有編譯錯(cuò)誤。

可是?swim?函數(shù)接受的參數(shù)是?Cat | Fish,一旦傳入的參數(shù)是?Cat?類型的變量,由于?Cat?上沒(méi)有?swim?方法,就會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤了。

總之,使用類型斷言時(shí)一定要格外小心,盡量避免斷言后調(diào)用方法或引用深層屬性,以減少不必要的運(yùn)行時(shí)錯(cuò)誤。

?2.2 將一個(gè)父類斷言為更加具體的子類

當(dāng)類之間有繼承關(guān)系時(shí),類型斷言也是很常見(jiàn)的:

class ApiError extends Error {
    code: number = 0;
}
class HttpError extends Error {
    statusCode: number = 200;
}

function isApiError(error: Error) {
    if (typeof (error as ApiError).code === 'number') {
        return true;
    }
    return false;
}

?上面的例子中,我們聲明了函數(shù)?isApiError,它用來(lái)判斷傳入的參數(shù)是不是?ApiError?類型,為了實(shí)現(xiàn)這樣一個(gè)函數(shù),它的參數(shù)的類型肯定得是比較抽象的父類?Error,這樣的話這個(gè)函數(shù)就能接受?Error?或它的子類作為參數(shù)了。

但是由于父類?Error?中沒(méi)有?code?屬性,故直接獲取?error.code?會(huì)報(bào)錯(cuò),需要使用類型斷言獲取?(error as ApiError).code

大家可能會(huì)注意到,在這個(gè)例子中有一個(gè)更合適的方式來(lái)判斷是不是?ApiError,那就是使用?instanceof

interface ApiError extends Error {
    code: number;
}
interface HttpError extends Error {
    statusCode: number;
}

function isApiError(error: Error) {
    if (error instanceof ApiError) {
        return true;
    }
    return false;
}

// index.ts:9:26 - error TS2693: 'ApiError' only refers to a type, but is being used as a value here.

此時(shí)就只能用類型斷言,通過(guò)判斷是否存在?code?屬性,來(lái)判斷傳入的參數(shù)是不是?ApiError?了:

interface ApiError extends Error {
    code: number;
}
interface HttpError extends Error {
    statusCode: number;
}

function isApiError(error: Error) {
    if (typeof (error as ApiError).code === 'number') {
        return true;
    }
    return false;
}

?2.3?將任何一個(gè)類型斷言為?any

理想情況下,TypeScript 的類型系統(tǒng)運(yùn)轉(zhuǎn)良好,每個(gè)值的類型都具體而精確。

當(dāng)我們引用一個(gè)在此類型上不存在的屬性或方法時(shí),就會(huì)報(bào)錯(cuò):

const foo: number = 1;
foo.length = 1;

// index.ts:2:5 - error TS2339: Property 'length' does not exist on type 'number'.

?上面的例子中,數(shù)字類型的變量?foo?上是沒(méi)有?length?屬性的,故 TypeScript 給出了相應(yīng)的錯(cuò)誤提示。

這種錯(cuò)誤提示顯然是非常有用的。

但有的時(shí)候,我們非常確定這段代碼不會(huì)出錯(cuò),比如下面這個(gè)例子:

window.foo = 1;

// index.ts:1:8 - error TS2339: Property 'foo' does not exist on type 'Window & typeof globalThis'.

上面的例子中,我們需要將?window?上添加一個(gè)屬性?foo,但 TypeScript 編譯時(shí)會(huì)報(bào)錯(cuò),提示我們?window?上不存在?foo?屬性。

此時(shí)我們可以使用?as any?臨時(shí)將?window?斷言為?any?類型:

(window as any).foo = 1;

?在?any?類型的變量上,訪問(wèn)任何屬性都是允許的。

需要注意的是,將一個(gè)變量斷言為?any?可以說(shuō)是解決 TypeScript 中類型問(wèn)題的最后一個(gè)手段。

它極有可能掩蓋了真正的類型錯(cuò)誤,所以如果不是非常確定,就不要使用?as any。

上面的例子中,我們也可以通過(guò)[擴(kuò)展 window 的類型(TODO)][]解決這個(gè)錯(cuò)誤,不過(guò)如果只是臨時(shí)的增加?foo?屬性,as any?會(huì)更加方便。

總之,一方面不能濫用?as any,另一方面也不要完全否定它的作用,我們需要在類型的嚴(yán)格性和開(kāi)發(fā)的便利性之間掌握平衡(這也是?TypeScript 的設(shè)計(jì)理念之一),才能發(fā)揮出 TypeScript 最大的價(jià)值。

2.4?將?any?斷言為一個(gè)具體的類型

在日常的開(kāi)發(fā)中,我們不可避免的需要處理?any?類型的變量,它們可能是由于第三方庫(kù)未能定義好自己的類型,也有可能是歷史遺留的或其他人編寫(xiě)的爛代碼,還可能是受到 TypeScript 類型系統(tǒng)的限制而無(wú)法精確定義類型的場(chǎng)景。

遇到?any?類型的變量時(shí),我們可以選擇無(wú)視它,任由它滋生更多的?any。

我們也可以選擇改進(jìn)它,通過(guò)類型斷言及時(shí)的把?any?斷言為精確的類型,亡羊補(bǔ)牢,使我們的代碼向著高可維護(hù)性的目標(biāo)發(fā)展。

舉例來(lái)說(shuō),歷史遺留的代碼中有個(gè)?getCacheData,它的返回值是?any

function getCacheData(key: string): any {
    return (window as any).cache[key];
}

那么我們?cè)谑褂盟鼤r(shí),最好能夠?qū)⒄{(diào)用了它之后的返回值斷言成一個(gè)精確的類型,這樣就方便了后續(xù)的操作:

function getCacheData(key: string): any {
    return (window as any).cache[key];
}

interface Cat {
    name: string;
    run(): void;
}

const tom = getCacheData('tom') as Cat;
tom.run();

?上面的例子中,我們調(diào)用完?getCacheData?之后,立即將它斷言為?Cat?類型。這樣的話明確了?tom?的類型,后續(xù)對(duì)?tom?的訪問(wèn)時(shí)就有了代碼補(bǔ)全,提高了代碼的可維護(hù)性。

類型斷言的限制

從上面的例子中,我們可以總結(jié)出:

  • 聯(lián)合類型可以被斷言為其中一個(gè)類型
  • 父類可以被斷言為子類
  • 任何類型都可以被斷言為 any
  • any 可以被斷言為任何類型

那么類型斷言有沒(méi)有什么限制呢?是不是任何一個(gè)類型都可以被斷言為任何另一個(gè)類型呢?

答案是否定的——并不是任何一個(gè)類型都可以被斷言為任何另一個(gè)類型。

具體來(lái)說(shuō),若?A?兼容?B,那么?A?能夠被斷言為?BB?也能被斷言為?A。

下面我們通過(guò)一個(gè)簡(jiǎn)化的例子,來(lái)理解類型斷言的限制:

interface Animal {
    name: string;
}
interface Cat {
    name: string;
    run(): void;
}

let tom: Cat = {
    name: 'Tom',
    run: () => { console.log('run') }
};
let animal: Animal = tom;

?我們知道,TypeScript 是結(jié)構(gòu)類型系統(tǒng),類型之間的對(duì)比只會(huì)比較它們最終的結(jié)構(gòu),而會(huì)忽略它們定義時(shí)的關(guān)系。

在上面的例子中,Cat?包含了?Animal?中的所有屬性,除此之外,它還有一個(gè)額外的方法?run。TypeScript 并不關(guān)心?Cat?和?Animal?之間定義時(shí)是什么關(guān)系,而只會(huì)看它們最終的結(jié)構(gòu)有什么關(guān)系——所以它與?Cat extends Animal?是等價(jià)的:

interface Animal {
    name: string;
}
interface Cat extends Animal {
    run(): void;
}

那么也不難理解為什么?Cat?類型的?tom?可以賦值給?Animal?類型的?animal?了——就像面向?qū)ο缶幊讨形覀兛梢詫⒆宇惖膶?shí)例賦值給類型為父類的變量。

我們把它換成 TypeScript 中更專業(yè)的說(shuō)法,即:Animal?兼容?Cat。

雙重?cái)嘌?/h3>

既然:

  • 任何類型都可以被斷言為 any
  • any 可以被斷言為任何類型

那么我們是不是可以使用雙重?cái)嘌?as any as Foo?來(lái)將任何一個(gè)類型斷言為任何另一個(gè)類型呢?

interface Cat {
    run(): void;
}
interface Fish {
    swim(): void;
}

function testCat(cat: Cat) {
    return (cat as any as Fish);
}

?在上面的例子中,若直接使用?cat as Fish?肯定會(huì)報(bào)錯(cuò),因?yàn)?Cat?和?Fish?互相都不兼容。

但是若使用雙重?cái)嘌裕瑒t可以打破「要使得?A?能夠被斷言為?B,只需要?A?兼容?B?或?B?兼容?A?即可」的限制,將任何一個(gè)類型斷言為任何另一個(gè)類型。

若你使用了這種雙重?cái)嘌裕敲词邪司攀欠浅ee(cuò)誤的,它很可能會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。

除非迫不得已,千萬(wàn)別用雙重?cái)嘌浴?/strong>

類型斷言 vs 類型轉(zhuǎn)換

類型斷言只會(huì)影響 TypeScript 編譯時(shí)的類型,類型斷言語(yǔ)句在編譯結(jié)果中會(huì)被刪除:

function toBoolean(something: any): boolean {
    return something as boolean;
}

toBoolean(1);
// 返回值為 1

在上面的例子中,將?something?斷言為?boolean?雖然可以通過(guò)編譯,但是并沒(méi)有什么用,代碼在編譯后會(huì)變成:

function toBoolean(something) {
    return something;
}

toBoolean(1);
// 返回值為 1

所以類型斷言不是類型轉(zhuǎn)換,它不會(huì)真的影響到變量的類型。

若要進(jìn)行類型轉(zhuǎn)換,需要直接調(diào)用類型轉(zhuǎn)換的方法:

function toBoolean(something: any): boolean {
    return Boolean(something);
}

toBoolean(1);
// 返回值為 true

類型斷言 vs 類型聲明

在這個(gè)例子中:

function getCacheData(key: string): any {
    return (window as any).cache[key];
}

interface Cat {
    name: string;
    run(): void;
}

const tom = getCacheData('tom') as Cat;
tom.run();

?我們使用?as Cat?將?any?類型斷言為了?Cat?類型。

但實(shí)際上還有其他方式可以解決這個(gè)問(wèn)題:

function getCacheData(key: string): any {
    return (window as any).cache[key];
}

interface Cat {
    name: string;
    run(): void;
}

const tom: Cat = getCacheData('tom');
tom.run();

上面的例子中,我們通過(guò)類型聲明的方式,將?tom?聲明為?Cat,然后再將?any?類型的?getCacheData('tom')?賦值給?Cat?類型的?tom

這和類型斷言是非常相似的,而且產(chǎn)生的結(jié)果也幾乎是一樣的——tom?在接下來(lái)的代碼中都變成了?Cat?類型。

類型斷言 vs 泛型

還是這個(gè)例子:

function getCacheData(key: string): any {
    return (window as any).cache[key];
}

interface Cat {
    name: string;
    run(): void;
}

const tom = getCacheData('tom') as Cat;
tom.run();

我們還有第三種方式可以解決這個(gè)問(wèn)題,那就是泛型:

function getCacheData<T>(key: string): T {
    return (window as any).cache[key];
}

interface Cat {
    name: string;
    run(): void;
}

const tom = getCacheData<Cat>('tom');
tom.run();

通過(guò)給?getCacheData?函數(shù)添加了一個(gè)泛型?<T>,我們可以更加規(guī)范的實(shí)現(xiàn)對(duì)?getCacheData?返回值的約束,這也同時(shí)去除掉了代碼中的?any,是最優(yōu)的一個(gè)解決方案。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-440209.html

到了這里,關(guān)于typeScript中的類型斷言和類型別名、字符串字面量類型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【python基礎(chǔ)】基本數(shù)據(jù)類型-字符串類型

    【python基礎(chǔ)】基本數(shù)據(jù)類型-字符串類型

    視頻講解: 字符串?dāng)?shù)據(jù)類型01 字符串就是一系列字符。在python中,用引號(hào)括起來(lái)文本內(nèi)容的都是字符串。 其語(yǔ)法格式為:‘文本內(nèi)容’或者“文本內(nèi)容” 編寫(xiě)程序如下所示 我們發(fā)現(xiàn)其中的引號(hào)可以是單引號(hào),也可以是雙引號(hào)。這樣的靈活性可以使我們進(jìn)行引號(hào)之間的嵌套。

    2024年02月06日
    瀏覽(27)
  • Rust類型之字符串

    Rust類型之字符串

    Rust 中的字符串類型是 String 。雖然字符串只是比字符多了一個(gè)“串”字,但是在Rust中這兩者的存儲(chǔ)方式完全不一樣,字符串不是字符的數(shù)組, String 內(nèi)部存儲(chǔ)的是 Unicode 字符串的 UTF8 編碼,而 char 直接存的是 Unicode Scalar Value 。 Rust字符串對(duì) Unicode 字符集有著良好的支持,可以

    2024年02月02日
    瀏覽(23)
  • .Net 根據(jù)類型全名字符串獲取類型信息

    asp.net項(xiàng)目開(kāi)發(fā)過(guò)程中用到了多個(gè)程序集(dll), 如何根據(jù)類型全名(fullname)獲取類型信息? 如果項(xiàng)目(csproj)中設(shè)置了引用對(duì)應(yīng)的dll 或nupkg包,但是代碼中沒(méi)有任務(wù)地方引用改該程序集的類,則實(shí)際上運(yùn)行時(shí),該程序集不會(huì)被加載到進(jìn)程中. 假設(shè)有一個(gè) ThirdModels.dll, 在該d

    2024年02月16日
    瀏覽(20)
  • python教程 入門(mén)學(xué)習(xí)筆記 第6天 數(shù)據(jù)類型轉(zhuǎn)換 字符串轉(zhuǎn)換成數(shù)值 數(shù)值之間互轉(zhuǎn) 其它類型轉(zhuǎn)字符串

    s1=\\\"188\\\" #字符串 ns1=int(s1) #轉(zhuǎn)換成整型數(shù)值 print(ns1+8) #打印數(shù)值結(jié)果 s1=\\\"3.14\\\" #字符串 ns1=float(s1) #轉(zhuǎn)換成浮點(diǎn)型數(shù)值 print(ns1+3) #打印數(shù)值結(jié)果(數(shù)值結(jié)果為6.140000000000001,出現(xiàn)誤差,后面講解決辦法) print(type(ns1)) #獲取新數(shù)值的數(shù)據(jù)類型屬性 z1=78 nz1=float(z1) print(nz1) #打印結(jié)果

    2024年02月14日
    瀏覽(45)
  • 時(shí)間字符串轉(zhuǎn)Date類型

    時(shí)間字符串轉(zhuǎn)Date類型

    天行健,君子以自強(qiáng)不息;地勢(shì)坤,君子以厚德載物。 每個(gè)人都有惰性,但不斷學(xué)習(xí)是好好生活的根本,共勉! 文章均為學(xué)習(xí)整理筆記,分享記錄為主,如有錯(cuò)誤請(qǐng)指正,共同學(xué)習(xí)進(jìn)步。 將字符串時(shí)間轉(zhuǎn)為Date類型的日期 如 2023年7月5號(hào)12點(diǎn)34分58秒的時(shí)間字符串20230705123458 轉(zhuǎn)

    2024年02月12日
    瀏覽(23)
  • 數(shù)據(jù)庫(kù)-列的類型-字符串char類型

    char 類型懂得都懂就是固定的字符串類型 char (maxLen)? 例如 char(5) 這個(gè)長(zhǎng)度為5 但插入數(shù)據(jù)‘a(chǎn)’時(shí) 是5 插入abc 也是5 即使插滿固定 就像C/C++語(yǔ)言里?char 字符數(shù)組一樣 maxLen==255? 哈哈最多有255個(gè)字符多了我認(rèn)為你是錯(cuò)誤? varchar 類型顧名思義可變字符串類型 varchar (maxLen)但 長(zhǎng)度可

    2024年02月02日
    瀏覽(31)
  • C++入門(mén)學(xué)習(xí)(十二)字符串類型

    C++入門(mén)學(xué)習(xí)(十二)字符串類型

    上一節(jié)(C++入門(mén)學(xué)習(xí)(十一)字符型-CSDN博客)中我們學(xué)到如何表示和使用一個(gè)字符串,本篇文章是字符串(多個(gè)字符)。 定義字符串主要有兩種方式: 第一種: char str[] = \\\"win\\\";? //char 變量名[] = \\\"字符串\\\" 第二種: #include string string str1 = \\\"winner\\\"; /?/ 兩種方式代碼: ?注意字符

    2024年01月23日
    瀏覽(19)
  • Stream——數(shù)字類型的字符串排序

    Stream——數(shù)字類型的字符串排序

    想到給數(shù)據(jù)進(jìn)行排序,一開(kāi)始頭腦中想到的就是 sorted() ,本篇文章重點(diǎn)說(shuō)明: 數(shù)字類型的字符串?dāng)?shù)據(jù)排序。 其他類型數(shù)據(jù)排序參考之前的文章:Stream——集合數(shù)據(jù)按照某一字段排序 數(shù)字類型的字符串,準(zhǔn)確說(shuō)是我自己定義的一個(gè) 名詞 ,就好比下列的數(shù)據(jù)類型。 \\\"1\\\" \\\"2\\\" 如標(biāo)

    2024年02月13日
    瀏覽(19)
  • 【?MySQL | 數(shù)據(jù)類型(二)】字符串 | 二進(jìn)制類型

    【?MySQL | 數(shù)據(jù)類型(二)】字符串 | 二進(jìn)制類型

    ?歡迎來(lái)到小K的MySQL專欄,本節(jié)將為大家?guī)?lái)MySQL字符串 | 二進(jìn)制類型類型的分享 ? 5 字符串類型 字符串類型用來(lái)存儲(chǔ)字符串?dāng)?shù)據(jù),還可以存儲(chǔ)圖片和聲音的二進(jìn)制數(shù)據(jù)。字符串可以區(qū)分或者不區(qū)分大小寫(xiě)的串比較,還可以進(jìn)行正則表達(dá)式的匹配查找。 下表中列出了 MySQL 中

    2024年02月11日
    瀏覽(23)
  • Python標(biāo)準(zhǔn)數(shù)據(jù)類型-String(字符串)

    Python標(biāo)準(zhǔn)數(shù)據(jù)類型-String(字符串)

    ?作者簡(jiǎn)介:CSDN內(nèi)容合伙人、阿里云專家博主、51CTO專家博主、新星計(jì)劃第三季python賽道Top1 ??個(gè)人主頁(yè):hacker707的csdn博客 ??系列專欄:零基礎(chǔ)入門(mén)篇 ??個(gè)人格言:不斷的翻越一座又一座的高山,那樣的人生才是我想要的。這一馬平川,一眼見(jiàn)底的活,我不想要,我的人生

    2024年02月03日
    瀏覽(25)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包