TS?高級(jí)類(lèi)型清單(附?Demo)

TypeScript 是一種類(lèi)型化的語(yǔ)言孝鹊,允許你指定變量的類(lèi)型,函數(shù)參數(shù)展蒂,返回的值和對(duì)象屬性又活。

你可以把本文看做一個(gè)帶有示例的 TypeScript 高級(jí)類(lèi)型備忘單

讓我們開(kāi)始吧!

Intersection Types(交叉類(lèi)型)

Union Types(聯(lián)合類(lèi)型)

Generic Types(泛型)

泛型函數(shù)

泛型接口

多參數(shù)的泛型類(lèi)型

Utility Types

Partial

Required

Readonly

Pick

Omit

Extract

Exclude

Record

NonNullable

Mapped Types( 映射類(lèi)型)

Type Guards(類(lèi)型保護(hù))

typeof

instanceof

in

Conditional Types(條件類(lèi)型)

Intersection Types(交叉類(lèi)型)

交叉類(lèi)型是一種將多種類(lèi)型組合為一種類(lèi)型的方法锰悼。 這意味著你可以將給定的類(lèi)型 A 與類(lèi)型 B 或更多類(lèi)型合并柳骄,并獲得具有所有屬性的單個(gè)類(lèi)型。

type LeftType = {

? ? id: number;

? ? left: string;

};

type RightType = {

? ? id: number;

? ? right: string;

};

type IntersectionType = LeftType & RightType;

function showType(args: IntersectionType) {

? ? console.log(args);

}

showType({ id: 1, left: 'test', right: 'test' });

// Output: {id: 1, left: "test", right: "test"}

如你所見(jiàn)松捉,IntersectionType組合了兩種類(lèi)型-LeftType和RightType夹界,并使用&符號(hào)形成了交叉類(lèi)型。

Union Types(聯(lián)合類(lèi)型)

聯(lián)合類(lèi)型使你可以賦予同一個(gè)變量不同的類(lèi)型

type UnionType = string | number;

function showType(arg: UnionType) {

? ? console.log(arg);

}

showType('test');

// Output: test

showType(7);

// Output: 7

函數(shù)showType是一個(gè)聯(lián)合類(lèi)型函數(shù)隘世,它接受字符串或者數(shù)字作為參數(shù)可柿。

Generic Types(泛型)

泛型類(lèi)型是復(fù)用給定類(lèi)型的一部分的一種方式。 它有助于捕獲作為參數(shù)傳遞的類(lèi)型 T丙者。

優(yōu)點(diǎn): 創(chuàng)建可重用的函數(shù)复斥,一個(gè)函數(shù)可以支持多種類(lèi)型的數(shù)據(jù)。 這樣開(kāi)發(fā)者就可以根據(jù)自己的數(shù)據(jù)類(lèi)型來(lái)使用函數(shù)

泛型函數(shù)

function showType<T>(args: T) {

? ? console.log(args);

}

showType('test');

// Output: "test"

showType(1);

// Output: 1

如何創(chuàng)建泛型類(lèi)型:需要使用<>并將 T(名稱(chēng)可自定義)作為參數(shù)傳遞械媒。 上面的? 栗子中目锭, 我們給 showType 添加了類(lèi)型變量 T。T幫助我們捕獲用戶傳入的參數(shù)的類(lèi)型(比如:number/string)之后我們就可以使用這個(gè)類(lèi)型

我們把 showType 函數(shù)叫做泛型函數(shù)纷捞,因?yàn)樗梢赃m用于多個(gè)類(lèi)型

泛型接口

interface GenericType<T> {

? ? id: number;

? ? name: T;

}

function showType(args: GenericType<string>) {

? ? console.log(args);

}

showType({ id: 1, name: 'test' });

// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<number>) {

? ? console.log(args);

}

showTypeTwo({ id: 1, name: 4 });

// Output: {id: 1, name: 4}

在上面的栗子中痢虹,聲明了一個(gè) GenericType 接口,該接口接收泛型類(lèi)型 T, 并通過(guò)類(lèi)型 T來(lái)約束接口內(nèi) name 的類(lèi)型

注:泛型變量約束了整個(gè)接口后主儡,在實(shí)現(xiàn)的時(shí)候奖唯,必須指定一個(gè)類(lèi)型

因此在使用時(shí)我們可以將name設(shè)置為任意類(lèi)型的值,示例中為字符串或數(shù)字

多參數(shù)的泛型類(lèi)型

interface GenericType<T, U> {

? ? id: T;

? ? name: U;

}

function showType(args: GenericType<number, string>) {

? ? console.log(args);

}

showType({ id: 1, name: 'test' });

// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<string, string[]>) {

? ? console.log(args);

}

showTypeTwo({ id: '001', name: ['This', 'is', 'a', 'Test'] });

// Output: {id: "001", name: Array["This", "is", "a", "Test"]}

泛型類(lèi)型可以接收多個(gè)參數(shù)糜值。 在上面的代碼中丰捷,我們傳入兩個(gè)參數(shù):T和U坯墨,然后將它們用作id,name的類(lèi)型。 也就是說(shuō)病往,我們現(xiàn)在可以使用該接口并提供不同的類(lèi)型作為參數(shù)。

Utility Types

TypeScript 內(nèi)部也提供了很多方便實(shí)用的工具停巷,可幫助我們更輕松地操作類(lèi)型少漆。 如果要使用它們,你需要將類(lèi)型傳遞給<>

Partial

Partial<T>

Partial 允許你將T類(lèi)型的所有屬性設(shè)為可選硼被。 它將在每一個(gè)字段后面添加一個(gè)?示损。

interface PartialType {

? ? id: number;

? ? firstName: string;

? ? lastName: string;

}

/*

等效于

interface PartialType {

? id?: number

? firstName?: string

? lastName?: string

}

*/

function showType(args: Partial<PartialType>) {

? ? console.log(args);

}

showType({ id: 1 });

// Output: {id: 1}

showType({ firstName: 'John', lastName: 'Doe' });

// Output: {firstName: "John", lastName: "Doe"}

上面代碼中聲明了一個(gè)PartialType接口,它用作函數(shù)showType()的參數(shù)的類(lèi)型嚷硫。 為了使所有字段都變?yōu)榭蛇x检访,我們使用Partial關(guān)鍵字并將PartialType類(lèi)型作為參數(shù)傳遞。

Required

Required<T>

將某個(gè)類(lèi)型里的屬性全部變?yōu)楸剡x項(xiàng)

interface RequiredType {

? ? id: number;

? ? firstName?: string;

? ? lastName?: string;

}

function showType(args: Required<RequiredType>) {

? ? console.log(args);

}

showType({ id: 1, firstName: 'John', lastName: 'Doe' });

// Output: { id: 1, firstName: "John", lastName: "Doe" }

showType({ id: 1 });

// Error: Type '{ id: number: }' is missing the following properties from type 'Required<RequiredType>': firstName, lastName

上面的代碼中仔掸,即使我們?cè)谑褂媒涌谥跋葘⒛承傩栽O(shè)為可選脆贵,但Required被加入后也會(huì)使所有屬性成為必選。 如果省略某些必選參數(shù)起暮,TypeScript 將報(bào)錯(cuò)卖氨。

Readonly

Readonly<T>

會(huì)轉(zhuǎn)換類(lèi)型的所有屬性,以使它們無(wú)法被修改

interface ReadonlyType {

? ? id: number;

? ? name: string;

}

function showType(args: Readonly<ReadonlyType>) {

? ? args.id = 4;

? ? console.log(args);

}

showType({ id: 1, name: 'Doe' });

// Error: Cannot assign to 'id' because it is a read-only property.

我們使用Readonly來(lái)使ReadonlyType的屬性不可被修改。 也就是說(shuō)纸厉,如果你嘗試為這些字段之一賦予新值系吭,則會(huì)引發(fā)錯(cuò)誤。

除此之外颗品,你還可以在指定的屬性前面使用關(guān)鍵字readonly使其無(wú)法被重新賦值

interface ReadonlyType {

? ? readonly id: number;

? ? name: string;

}

Pick

Pick<T, K>

此方法允許你從一個(gè)已存在的類(lèi)型 T中選擇一些屬性作為K, 從而創(chuàng)建一個(gè)新類(lèi)型

即 抽取一個(gè)類(lèi)型/接口中的一些子集作為一個(gè)新的類(lèi)型

T代表要抽取的對(duì)象 K有一個(gè)約束: 一定是來(lái)自T所有屬性字面量的聯(lián)合類(lèi)型 新的類(lèi)型/屬性一定要從K中選取肯尺,

/**

? ? 源碼實(shí)現(xiàn)

* From T, pick a set of properties whose keys are in the union K

*/

type Pick<T, K extends keyof T> = {

? ? [P in K]: T[P];

};

interface PickType {

? ? id: number;

? ? firstName: string;

? ? lastName: string;

}

function showType(args: Pick<PickType, 'firstName' | 'lastName'>) {

? ? console.log(args);

}

showType({ firstName: 'John', lastName: 'Doe' });

// Output: {firstName: "John"}

showType({ id: 3 });

// Error: Object literal may only specify known properties, and 'id' does not exist in type 'Pick<PickType, "firstName" | "lastName">'

Pick 與我們前面討論的工具有一些不同,它需要兩個(gè)參數(shù)

T是要從中選擇元素的類(lèi)型

K是要選擇的屬性(可以使使用聯(lián)合類(lèi)型來(lái)選擇多個(gè)字段)

Omit

Omit<T, K>

Omit的作用與Pick類(lèi)型正好相反锄蹂。 不是選擇元素逾滥,而是從類(lèi)型T中刪除K個(gè)屬性。

interface PickType {

? ? id: number;

? ? firstName: string;

? ? lastName: string;

}

function showType(args: Omit<PickType, 'firstName' | 'lastName'>) {

? ? console.log(args);

}

showType({ id: 7 });

// Output: {id: 7}

showType({ firstName: 'John' });

// Error: Object literal may only specify known properties, and 'firstName' does not exist in type 'Pick<PickType, "id">'

Extract

Extract<T, U>

提取T中可以賦值給U的類(lèi)型--取交集

Extract允許你通過(guò)選擇兩種不同類(lèi)型中的共有屬性來(lái)構(gòu)造新的類(lèi)型。 也就是從T中提取所有可分配給U的屬性寨昙。

interface FirstType {

? ? id: number;

? ? firstName: string;

? ? lastName: string;

}

interface SecondType {

? ? id: number;

? ? address: string;

? ? city: string;

}

type ExtractType = Extract<keyof FirstType, keyof SecondType>;

// Output: "id"

在上面的代碼中,F(xiàn)irstType接口和SecondType接口掀亩,都存在 id:number屬性舔哪。 因此,通過(guò)使用Extract槽棍,即提取出了新的類(lèi)型 {id:number}捉蚤。

Exclude

Exclude<T, U> --從 T 中剔除可以賦值給 U 的類(lèi)型。

與Extract不同炼七,Exclude通過(guò)排除兩個(gè)不同類(lèi)型中已經(jīng)存在的共有屬性來(lái)構(gòu)造新的類(lèi)型缆巧。 它會(huì)從T中排除所有可分配給U的字段。

interface FirstType {

? ? id: number;

? ? firstName: string;

? ? lastName: string;

}

interface SecondType {

? ? id: number;

? ? address: string;

? ? city: string;

}

type ExcludeType = Exclude<keyof FirstType, keyof SecondType>;

// Output; "firstName" | "lastName"

上面的代碼可以看到豌拙,屬性firstName和lastName 在SecondType類(lèi)型中不存在陕悬。 通過(guò)使用Extract關(guān)鍵字,我們可以獲得T中存在而U中不存在的字段按傅。

Record

Record<K,T>

此工具可幫助你構(gòu)造具有給定類(lèi)型T的一組屬性K的類(lèi)型捉超。將一個(gè)類(lèi)型的屬性映射到另一個(gè)類(lèi)型的屬性時(shí),Record非常方便唯绍。

interface EmployeeType {

? ? id: number;

? ? fullname: string;

? ? role: string;

}

let employees: Record<number, EmployeeType> = {

? ? 0: { id: 1, fullname: 'John Doe', role: 'Designer' },

? ? 1: { id: 2, fullname: 'Ibrahima Fall', role: 'Developer' },

? ? 2: { id: 3, fullname: 'Sara Duckson', role: 'Developer' },

};

// 0: { id: 1, fullname: "John Doe", role: "Designer" },

// 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },

// 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }

Record的工作方式相對(duì)簡(jiǎn)單拼岳。 在代碼中,它期望一個(gè)number作為類(lèi)型况芒,這就是為什么我們將 0惜纸、1 和 2 作為employees變量的鍵的原因。 如果你嘗試使用字符串作為屬性绝骚,則會(huì)引發(fā)錯(cuò)誤,因?yàn)閷傩允怯蒃mployeeType給出的具有 ID耐版,fullName 和 role 字段的對(duì)象。

NonNullable

NonNullable<T>

-- 從 T 中剔除 null 和 undefined

type NonNullableType = string | number | null | undefined;

function showType(args: NonNullable<NonNullableType>) {

? ? console.log(args);

}

showType('test');

// Output: "test"

showType(1);

// Output: 1

showType(null);

// Error: Argument of type 'null' is not assignable to parameter of type 'string | number'.

showType(undefined);

// Error: Argument of type 'undefined' is not assignable to parameter of type 'string | number'.

我們將類(lèi)型NonNullableType作為參數(shù)傳遞給NonNullable皮壁,NonNullable通過(guò)排除null和undefined來(lái)構(gòu)造新類(lèi)型椭更。 也就是說(shuō),如果你傳遞可為空的值蛾魄,TypeScript 將引發(fā)錯(cuò)誤虑瀑。

順便說(shuō)一句,如果將--strictNullChecks標(biāo)志添加到tsconfig文件滴须,TypeScript 將應(yīng)用非空性規(guī)則。

Mapped Types( 映射類(lèi)型)

映射類(lèi)型允許你從一個(gè)舊的類(lèi)型扔水,生成一個(gè)新的類(lèi)型。

請(qǐng)注意,前面介紹的某些高級(jí)類(lèi)型也是映射類(lèi)型主届。 如:

/*

Readonly, Partial和 Pick是同態(tài)的君丁,但 Record不是。 因?yàn)?Record并不需要輸入類(lèi)型來(lái)拷貝屬性绘闷,所以它不屬于同態(tài):

*/

type Readonly<T> = {

? ? readonly [P in keyof T]: T[P];

};

type Partial<T> = {

? ? [P in keyof T]?: T[P];

};

type Pick<T, K extends keyof T> = {

? ? [P in K]: T[P];

};

Record;

type StringMap<T> = {

? ? [P in keyof T]: string;

};

function showType(arg: StringMap<{ id: number; name: string }>) {

? ? console.log(arg);

}

showType({ id: 1, name: 'Test' });

// Error: Type 'number' is not assignable to type 'string'.

showType({ id: 'testId', name: 'This is a Test' });

// Output: {id: "testId", name: "This is a Test"}

StringMap<>會(huì)將傳入的任何類(lèi)型轉(zhuǎn)換為字符串。 就是說(shuō)扒最,如果我們?cè)诤瘮?shù)showType()中使用它,則接收到的參數(shù)必須是字符串-否則吧趣,TypeScript 將引發(fā)錯(cuò)誤。

Type Guards(類(lèi)型保護(hù))

類(lèi)型保護(hù)使你可以使用運(yùn)算符檢查變量或?qū)ο蟮念?lèi)型除呵。 這是一個(gè)條件塊再菊,它使用typeof,instanceof或in返回類(lèi)型颜曾。

typescript 能夠在特定區(qū)塊中保證變量屬于某種確定類(lèi)型纠拔。可以在此區(qū)塊中放心地引用此類(lèi)型的屬性泛豪,或者調(diào)用此類(lèi)型的方法

typeof

function showType(x: number | string) {

? ? if (typeof x === 'number') {

? ? ? ? return `The result is ${x + x}`;

? ? }

? ? throw new Error(`This operation can't be done on a ${typeof x}`);

}

showType("I'm not a number");

// Error: This operation can't be done on a string

showType(7);

// Output: The result is 14

什么代碼中稠诲,有一個(gè)普通的 JavaScript 條件塊,通過(guò)typeof檢查接收到的參數(shù)的類(lèi)型诡曙。

instanceof

class Foo {

? ? bar() {

? ? ? ? return 'Hello World';

? ? }

}

class Bar {

? ? baz = '123';

}

function showType(arg: Foo | Bar) {

? ? if (arg instanceof Foo) {

? ? ? ? console.log(arg.bar());

? ? ? ? return arg.bar();

? ? }

? ? throw new Error('The type is not supported');

}

showType(new Foo());

// Output: Hello World

showType(new Bar());

// Error: The type is not supported

像前面的示例一樣臀叙,這也是一個(gè)類(lèi)型保護(hù),它檢查接收到的參數(shù)是否是Foo類(lèi)的一部分价卤,并對(duì)其進(jìn)行處理劝萤。

in

interface FirstType {

? ? x: number;

}

interface SecondType {

? ? y: string;

}

function showType(arg: FirstType | SecondType) {

? ? if ('x' in arg) {

? ? ? ? console.log(`The property ${arg.x} exists`);

? ? ? ? return `The property ${arg.x} exists`;

? ? }

? ? throw new Error('This type is not expected');

}

showType({ x: 7 });

// Output: The property 7 exists

showType({ y: 'ccc' });

// Error: This type is not expected

什么的栗子中,使用in檢查參數(shù)對(duì)象上是否存在屬性x慎璧。

Conditional Types(條件類(lèi)型)

條件類(lèi)型測(cè)試兩種類(lèi)型床嫌,然后根據(jù)該測(cè)試的結(jié)果選擇其中一種。

一種由條件表達(dá)式所決定的類(lèi)型胸私, 表現(xiàn)形式為 T extends U ? X : Y , 即如果類(lèi)型T可以被賦值給類(lèi)型U厌处,那么結(jié)果類(lèi)型就是X類(lèi)型,否則為Y類(lèi)型岁疼。

條件類(lèi)型使類(lèi)型具有了不唯一性阔涉,增加了語(yǔ)言的靈活性,

// 源碼實(shí)現(xiàn)

type NonNullable<T> = T extends null | undefined ? never : T;

// NotNull<T> 等價(jià)于 NoneNullable<T,U>

// 用法示例

type resType = NonNullable<string | number | null | undefined>; // string|number

上面的代碼中, NonNullable檢查類(lèi)型是否為 null瑰排,并根據(jù)該類(lèi)型進(jìn)行處理贯要。 正如你所看到的,它使用了 JavaScript 三元運(yùn)算符凶伙。

恭喜您讀到這里郭毕,如果想了解更多技術(shù),可以訪問(wèn)我的網(wǎng)站:路條編程函荣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扳肛,隨后出現(xiàn)的幾起案子傻挂,更是在濱河造成了極大的恐慌金拒,老刑警劉巖套腹,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件电禀,死亡現(xiàn)場(chǎng)離奇詭異尖飞,居然都是意外死亡政基,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)辕坝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酱畅,“玉大人圣贸,你說(shuō)我怎么就攤上這事吁峻。” “怎么了矮慕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵痴鳄,是天一觀的道長(zhǎng)痪寻。 經(jīng)常有香客問(wèn)我橡类,道長(zhǎng)顾画,這世上最難降的妖魔是什么匆笤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任庶诡,我火速辦了婚禮寓盗,結(jié)果婚禮上傀蚌,老公的妹妹穿的比我還像新娘。我一直安慰自己撩幽,他們只是感情好窜醉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布榨惰。 她就那樣靜靜地躺著琅催,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侠碧。 梳的紋絲不亂的頭發(fā)上缠黍,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天替饿,我揣著相機(jī)與錄音贸典,去河邊找鬼瓤漏。 笑死蔬充,一個(gè)胖子當(dāng)著我的面吹牛饥漫,可吹牛的內(nèi)容都是我干的罗标。 我是一名探鬼主播闯割,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宙拉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了煌贴?” 一聲冷哼從身側(cè)響起牛郑,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤淹朋,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后酪惭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體春感,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鲫懒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年窥岩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颂翼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朦乏。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呻疹,死狀恐怖筹陵,靈堂內(nèi)的尸體忽然破棺而出朦佩,到底是詐尸還是另有隱情,我是刑警寧澤纺荧,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布宙暇,位于F島的核電站占贫,受9級(jí)特大地震影響先口,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜厢汹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一界弧、第九天 我趴在偏房一處隱蔽的房頂上張望搭综。 院中可真熱鬧,春花似錦条获、人聲如沸帅掘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寓免。三九已至袜香,卻和暖如春鲫惶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欢策。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工踩寇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俺孙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓荣茫,卻偏偏與公主長(zhǎng)得像啡莉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子票罐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容