摘要:空類型,一般用來表示函數(shù)沒有返回值。返回值的類型則跟在參數(shù)的括號后面,冒號后面跟一個返回值的類型。箭頭函數(shù)參數(shù)與返回值的聲明方法與普通函數(shù)無二。函數(shù)重載當(dāng)一個函數(shù)在入?yún)⒉煌瑫r有較大的行為差距時,可以使用函數(shù)重載梳理代碼結(jié)構(gòu)。
類型系統(tǒng)是 typescript 最吸引人的特性之一,但它的強大也讓我們又愛又恨,每個前端同學(xué)在剛從 javascript 切換到 typescript 時都會有一段手足無措的時光,為了不讓編譯器報錯恨不得把所有變量都標注成 any 類型,而后在不斷地填坑中流下悔恨的淚水。Change Log 2018-11-14謹以此文記錄我在學(xué)習(xí) typescript 類型系統(tǒng)使用方法的過程中遇到的一些問題,以供大家參考,避免大腦進水。
(本文默認所有讀者熟知活動所有 ES6 語法及特性)
改正了枚舉與 .d.ts 文件的說明
2018-11-13修正了 .d.ts 一節(jié)中 class 在 .d.ts 文件中定義時使用了 export default 語法的問題
增加了 .d.ts 文件的使用注意事項
增加了枚舉(enum)不能定義在 .d.ts 文件中的說明
增加了枚舉(enum)部分對于為什么要使用 type xxx = "a" | "b" 來替換枚舉進行了說明
0x00 無知 類型聲明 基礎(chǔ)類型直接將類型附在變量聲明之后,并以冒號分隔。
const count: number = 3; const name: string = "apples"; const appleCounts: string = count + name; assert.strictEqual(appleCounts, "3apples");引用類型
稍微復(fù)雜一點的,如數(shù)組 & 對象,按照其內(nèi)成員結(jié)構(gòu)進行聲明。
const object: { a: number } = { a: 1, }; const array1: number[] = [1,]; const array2: Array函數(shù)類型= [2,];
寫法極像箭頭函數(shù)。
const someFn: (str: string) => number = function (str: string) { return +str; }typescript 擴展的輔助類型 any
啥都能放,但并不建議大量使用,如果所有變量都是 any,那 typescript 跟 javascript 又有什么區(qū)別呢。
const variable: any = "5";void
空類型,一般用來表示函數(shù)沒有返回值。
function someFn (): void { 1 + 1; }類型并聯(lián)
當(dāng)一個變量可能是多種類型時,使用 | 進行多個不同類型的分隔:
const nos: number | string = "1";在引用類型中使用
錯誤用法
一定,一定,一定 不要用 , 作分隔符。
const object: { a: [number, string] } = { a: 1, };
正確用法
const object: { a: number | string } = { a: 1, }; const array1: (number | string)[] = [ 1, ]; const array2: Array= [ 2, ];
或
type numberOstring = number | string; const object: { a: numberOstring } = { a: "yes", }; const array1: numberOstring[] = [ "yes", ]; const array2: Array在函數(shù)入?yún)?& 出參中聲明類型= [ "yes", ];
函數(shù)的入?yún)㈩愋透暶髯兞康念愋蜁r差不多,直接在變量名后跟類型名稱就可以了。
返回值的類型則跟在參數(shù)的括號后面,冒號后面跟一個返回值的類型。
function someFn (arg1: string, arg2: number): boolean { return +arg1 > arg2; }箭頭函數(shù)
參數(shù)與返回值的聲明方法與普通函數(shù)無二。
setTimeout((): void => { console.log("six six six"); }, 50);在類中聲明類型
實例屬性記得一定要初始化。
class SomeClass { a: number = 1; b: string; static a: boolean; constructor () { this.b = "str"; } method (str: string): number { return +str; } }類型轉(zhuǎn)換
當(dāng)你在聲明一個普通的對象(其他類型也有可能,此處僅使用對象作為例子)時,typescript 并不會自動為你添加上對應(yīng)的類型,這會造成你在賦值時觸發(fā) TS2322: Type "xxx" is not assignable to type "xxx". 錯誤,此時就需要使用顯式類型轉(zhuǎn)換來將兩邊的類型差異抹平。
類型轉(zhuǎn)換的前提是當(dāng)前類型是真的可以轉(zhuǎn)換為目標類型的,任何必選屬性的缺失,或是根本無法轉(zhuǎn)換的類型都是不允許的。
并不推薦這種方法,因為有時編輯器會把它當(dāng)成 jsx 處理,產(chǎn)生不必要的 warning。
const object1: object = { a: 1, }; const object2: { a: number } = <{ a: number }>object1;as 表達式轉(zhuǎn)換
const object1: object = { a: 1, }; const object2: { a: number } = object1 as { a: number };0x01 理智 自定義類型
相當(dāng)于聯(lián)結(jié)多個不同類型,并為他們創(chuàng)造一個假名,平時寫多個類型并聯(lián)實在是太累了的時候可以試試這個方法。
它的值可以是類型,也可以是具體的變量值。
type NumberOrString = number | string; type Direction = "Up" | "Right" | "Down" | "Left"; const num: NumberOrString = 1; const dir: Direction = "Up";枚舉 官方
注意:枚舉內(nèi)部賦值時如果為數(shù)字,可以只賦值第一個,后面幾個會隨之遞增,如果為字符串,則需要全部賦值,否則就會報錯。
enum Direction { Up = 1, Right, Down, Left } const dir: Direction = Direction.Up;我的方法
如果你的代碼中準備使用 enum 作為右值,那請不要把 enum 聲明在 .d.ts 文件中,這是因為 ts 在編譯的時候 .d.ts 文件是作為類型文件用的,并不會生成實體輸出,自然也就沒有地方會定義這個枚舉,這個時候用在代碼里作為右值的枚舉值就會因為找不到整個枚舉的定義,從而觸發(fā) "xxx is undefined" 錯誤。
這也使得它在使用過程中給我們造成了各種各樣的麻煩(在 .d.ts 的 interface 聲明中使用 enum 真的是再正常不過的事情了),比如:
// my-types.d.ts declare const enum Direction { Up = 0, Right = 1, Down = 2, Left = 3, }
// usage.ts class SomeClass { dir = Direction.Up; }
編譯后的結(jié)果是:
// .d.ts 文件當(dāng)場消失
// usage.js function SomeClass () { this.dir = Direction.up; }
瀏覽器在運行時根本找不到 Direction 定義的位置,自然就報 "Direction" is not defined 的錯了,但 type Direction = "Up" | "Right" | "Down" | "Left" 的方法就不會有這種問題,具體使用方式如下:
// my-types.d.ts type Direction = "Up" | "Right" | "Down" | "Left";
// usage.ts const dir: Direction = "Up";
缺點是沒有類型提示,不能定義枚舉的內(nèi)部值,判斷的時候也必須用對應(yīng)的字符串進行字符串比對(汗。
接口 基礎(chǔ)聲明一種類型的對象,該類型的變量都必須滿足該結(jié)構(gòu)要求。
interface SomeInterface { str: string; num: number; } const object: SomeInterface = { str: "str", num: 1, }; class SomeClass implements SomeInterface { num = 1; constructor () { this.str = "str"; } }多重實現(xiàn)
同一個類可以實現(xiàn)多個不同的接口,但前提是該類一定要實現(xiàn)每個接口所要求的屬性。
interface Interface1 { str: string; } interface Interface2 { num: number; } class SomeClass implements Interface1, Interface2 { num = 1; constructor () { this.str = "str"; } }聲明合并
在多個不同文件,或是相同文件的不同位置聲明的同名接口,將會被合并成一個接口,名稱不變,成員變量取并集。
interface SomeInterface { str: string; } interface SomeInterface { num: number; } // 必須全部實現(xiàn) const someInterface: SomeInterface = { str: "str", num: 1, };函數(shù)接口 基礎(chǔ)使用
interface InterfaceFn { (str: string): boolean; } const fn1: InterfaceFn = (str: string): boolean => { return 10 < str.length; };當(dāng)該類函數(shù)還具有成員變量和方法時
interface InterfaceFn { (str: string): boolean; standard: string; someFn(num: number): string; } // 必須進行顯式類型轉(zhuǎn)換 let fn1: InterfaceFn = function (str: string): boolean { return 10 < str.length; } as InterfaceFn; fn1.standard = "str"; fn1.someFn = function (num: number): string { return `${num}`; };繼承
接口可以繼承類或是另一個接口,與 ES6 繼承方法語法一樣,在此不再贅述。
函數(shù) & 接口的缺省值及可選項當(dāng)該參數(shù)為可選項時,可以在名稱與類型表達式的冒號之間加一個問號 ? 用來表示該參數(shù)為 __可選項__。
function someFn (arg1: number, arg2?: string): void {} someFn(1);
當(dāng)該參數(shù)在不傳的時候有 缺省值 時,可以使用 = 來為其賦予 __缺省值__。
function someFn (arg1: number, arg2: number = 1): number { return arg1 + arg2; } someFn(1); // 2
可選項與 缺省值 可以混搭。
function someFn (arg1: number, arg2: string = "str", arg3?: string): void {} someFn(1);
但 可選項 參數(shù)后不可跟任何 非可選項 參數(shù)。(以下代碼當(dāng)場爆炸)
function someFn (arg1: number, arg2?: string, arg3: string = "str"): void {} someFn(1);
可選項與 缺省值 不可同時使用在同一個值上。(以下代碼當(dāng)場爆炸)
function someFn (arg1: number, arg2?: string = "str"): void {} someFn(1);
可選項 也可用在接口的聲明中(__缺省值__ 不行,因為接口是一種類型的聲明,并非具體實例的實現(xiàn))。
泛型 泛型函數(shù) 基礎(chǔ)類型function someFn同時使用多個泛型(arg:T): T { return arg; } const str1: string = someFn ("str1"); const str2: string = someFn("str2");
function someFn箭頭函數(shù) & 泛型類型(arg1: T, arg2: U): T | U { return arg1; } const num1: string | number = someFn ("str1", 1); const str2: string | number = someFn("str2", 2);
const someFn:泛型接口(arg: T) => T = (arg: T): T => { return arg; }; const str: string = someFn("str");
interface InterfaceFn {(arg: T): T; } const someFn: InterfaceFn = (arg: T): T => { return arg; }; const str: string = someFn("str");
const someFn: {(arg: T): T; } = (arg: T): T => { return arg; }; const str: string = someFn("str");
interface InterfaceFn泛型類{ (arg: T): T; } const someFn: InterfaceFn = (arg: T): T => { return arg; }; const str: string = someFn("str");
原理與 接口泛型 一樣。
class SomeClass泛型約束{ someMethod (arg: T): T { return arg; } }
function someFn(arg: T): number { return arg.getTime(); } const date = new Date();
keyof、Record、Pick、Partial 太過復(fù)雜,真有需求還請自行查閱文檔。
.d.ts 文件在實際編碼過程中,我們經(jīng)常會定義很多自定義的 接口 與 __類__,如果我們在聲明變量的類型時需要用到它們,就算我們的代碼中并沒有調(diào)用到它們的實例,我們也必須手動引入它們(最常見的例子是各種包裝類,他們并不會處理參數(shù)中傳入的變量,但他們會在接口上強規(guī)范參數(shù)的類型,并且會將該變量透傳給被包裝的類的對應(yīng)方法上)。
// foo.ts export default class FooClass { propA: number = 5; }
// bar.ts import FooClass from "./foo.ts"; export class BarClass { foo?: FooClass; }
這種使用方法在調(diào)用數(shù)量較少時尚且可以接受,但隨著業(yè)務(wù)的成長,被引用類型的數(shù)量和引用類型文件的數(shù)量同時上升,需要付出的精力便會隨其呈現(xiàn)出 o(n^2) 的增長趨勢。
這時我們可以選擇使用 .d.ts 文件,在你的業(yè)務(wù)目錄中創(chuàng)建 typings 文件夾,并在其內(nèi)新建屬于你的 xxx.d.ts 文件,并在其中對引用較多的類和接口進行聲明(.d.ts 文件是用來進行接口聲明的,不要在 .d.ts 文件里對聲明的結(jié)構(gòu)進行實現(xiàn))。
注意:.d.ts 文件只是用于分析類型聲明及傳參校驗,如果需要進行調(diào)用,還請直接 import 對應(yīng)模塊。
// my-types.d.ts declare class FooClass { propA: number; methodA (arg1: string): void; }
foo.ts 文件略
// bar.ts // 不需要再 import 了 export default class BarClass { foo?: FooClass; }
其他類型的聲明方式
// my-types.d.ts // 接口(沒有任何變化) interface InterfaceMy { propA: number; } // 函數(shù) function myFn (arg1: string): number; // 類型 type myType = number | string;使用注意
.d.ts 文件是類型聲明文件,不是具體業(yè)務(wù)模塊,不會產(chǎn)生具體的代碼實體,所以請在聲明模塊時使用 declare 關(guān)鍵字,且不要使用 export 語句(如果使用了 export,該文件就會變成實體 ts 文件,不會被 ts 的自動類型解析所識別,只能通過 import 使用)
枚舉(enum)一定不要定義在 .d.ts 里,這樣根本就引用不到(大概因為 typescript 的編譯過程是 文件 to 文件 的,所以本身作為數(shù)據(jù)類型輔助文件的 .d.ts 文件不會有翻譯實體的產(chǎn)出,自然也就無法在其內(nèi)定義一個右值字段(枚舉的每個值是可以作為右值使用的),那么其他引用這個字段的地方自然也就無法引用到這個值,繼而報錯了)
0x02 反思本來想寫一寫常見的 TS 編譯錯誤及造成這些錯誤的原因來著,后來想了想,編譯出錯了都不會查,還寫什么 TS 啊,
0xFF 失智以下幾點是我在使用 typescript 類型系統(tǒng)過程中遇到的一些智障問題與未解的疑問,歡迎大家一起討論。
為 window 變量增添屬性的各種姿勢錯誤的為 window 增添屬性的姿勢:
window.someProperty = 1;
會觸發(fā) TS2339: Property "xxx" does not exist on type "Window" 錯誤。
類型轉(zhuǎn)換法(window as any).someProperty = 1; (接口擴展法window).someProperty = 1;
利用接口可以多處聲明,由編譯器進行合并的特性進行 hack。
interface Window { someProperty: number; } window.someProperty = 1;為什么對象類型最后不能跟尾逗號
下面的代碼當(dāng)場爆炸(因為 c: number, 最后的這個逗號)。
const someObject: { a: number, b: number, c: number, } = { a: 1, b: 2, c: 3, };函數(shù)重載
當(dāng)一個函數(shù)在入?yún)⒉煌瑫r有較大的行為差距時,可以使用函數(shù)重載梳理代碼結(jié)構(gòu)。
注意:參數(shù)中有回調(diào)函數(shù)時,回調(diào)函數(shù)的參數(shù)數(shù)量變化并不應(yīng)該導(dǎo)致外層函數(shù)使用重載,只應(yīng)當(dāng)在當(dāng)前聲明函數(shù)的參數(shù)數(shù)量有變時才使用重載。
當(dāng)同時聲明多個重載時,較為準確的重載應(yīng)該放在更前面。
使用說明重載的使用方法比較智障,需要先 聲明 這個函數(shù)的不同重載方式,然后緊接著再對這個函數(shù)進行定義。
定義時的參數(shù)個數(shù)取不同重載方法中參數(shù)個數(shù)最少的數(shù)量,隨后在其后追加 ...args: any[](或者更為準確的類型定義寫法),用于接收多余的參數(shù)。
定義的返回值為所有重載返回值的并集。
而后在函數(shù)體內(nèi)部實現(xiàn)時,通過判斷參數(shù)類型,自行實現(xiàn)功能的分流。
問題神奇的是 typescript 并不會校驗重載的實現(xiàn)是否會真的在調(diào)用某個重載時返回這個重載真正要求的類型的值,下方例子中即使無論觸發(fā)哪個重載,都會返回 number,也不會被 typescript 檢查出來。
猜想:多次聲明一次實現(xiàn)難道是受制于 javascript 既有的語言書寫格式?
函數(shù)重載 of 類成員方法class SomeClass { someMethod (arg1: number, arg2: string, arg3: boolean): boolean; someMethod (arg1: number, arg2: string): string; someMethod (arg1: { arg1: number, arg2: string, }): number; someMethod (x: any, ...args: any[]): string | number | boolean { if ("object" === typeof x) { return 1; } else if (1 === args.length) { return 1; } else { return 1; } } }函數(shù)重載 of 函數(shù)
function someFn (arg1: number, arg2: string, arg3: boolean): boolean; function someFn (arg1: number, arg2: string): string; function someFn (arg1: { arg1: number, arg2: string, }): number; function someFn (x: any, ...args: any[]): string | number | boolean { if ("object" === typeof x) { return 1; } else if (1 === args.length) { return 1; } else { return 1; } }對象 key 的類型定義(索引標記)
可以使用 type、interface、class 對象 key,但是使用方法十分麻煩,而且語法還不太一樣(type 使用 in,interface 與 class 使用 :)。
注意:索引值只可以使用數(shù)字與字符串。
type 法 限定 key 的數(shù)據(jù)類型其實就是放開了限制,讓該類型的實例上可以添加各種各樣的屬性。
這里冒號 : 形式的不允許使用問號(可選項),但 in 形式的允許使用問號(可選項)。
但其實帶不帶結(jié)果都一樣,實例都可以為空。
type SomeType1 = { [key: string]: string; } type SomeType2 = { [key in string]?: string; } const instance1: SomeType1 = {}; const instance2: SomeType2 = {};限定 key 只可以使用特定值
這里其中的 key 就成了必選項了,問號(可選項)也有效果了。
type audioTypes = "ogg" | "mp3" | "wma"; type SomeType1 = { [key in audioTypes]: string; } type SomeType2 = { [key in audioTypes]?: string; } const instance5: SomeType1 = { "ogg": "ogg", "mp3": "mp3", "wma": "wma", }; const instance6: SomeType2 = {};interface 法 限定 key 的數(shù)據(jù)類型
不可以用問號。
interface SomeInterface { [key: string]: string; } const instance: SomeInterface = {};限定 key 只可以使用特定值
只能通過 extends 已定義的 type 來實現(xiàn)。
type audioTypes = "ogg" | "mp3" | "wma"; type SomeType = { [key in audioTypes]: string; } interface SomeInterface extends SomeType {} const instance: SomeInterface = { ogg: "ogg", mp3: "mp3", wma: "wma", };class 中的使用 限定 key 的數(shù)據(jù)類型
同樣也不可以使用問號(可選值)。
class SomeClass { [key: string]: string; } const instance: SomeClass = new SomeClass();限定 key 只可以使用特定值
通過 implements 其他的 interface、type 實現(xiàn)(多重實現(xiàn)可以合并)。
請記得 interface 只是數(shù)據(jù)格式規(guī)范,implements 之后要記得在 class 里寫實現(xiàn)
type audioTypes = "ogg" | "mp3" | "wma"; type SomeType = { [key in audioTypes]: string; } interface SomeInterface { [key: string]: string; } class ClassExtended implements SomeInterface, SomeType { ogg = "ogg"; mp3 = "mp3"; wma = "wma"; [key: string]: string; } const instance = new ClassExtended();如何初始化函數(shù)類變量?
初始化函數(shù)類變量時,是否需要既給左值聲明類型,也給右值聲明類型?
這樣的語句應(yīng)如何斷句換行 & 換行后如何縮進?
const someFn: (input: number, target: object) => SomeClass = (input: number, target: object): SomeClass => { // ... do sth };類型聲明 & npm 包版本
我們在平時使用一些類庫時,某一生態(tài)環(huán)境下的多個包,可能會依賴同一個基礎(chǔ)包。同一個生態(tài)環(huán)境下的包,更新節(jié)奏或快或慢,此時便可能會存在基礎(chǔ)包版本不同的問題,npm 的解決方案是多版本共存,每個包引用自己對應(yīng)版本的基礎(chǔ)包。因為 typescript 的類型是基于文件進行定義的,內(nèi)部結(jié)構(gòu)完全相同的兩個同名類型,在不同的文件中聲明便成了不同的類型。
此處以 @forawesome 項目組下的 fontawesome 庫進行舉例,具體示例如下:
當(dāng)我們在 vue 中使用 fortawesome 時,需要把圖標文件從對應(yīng)的包中導(dǎo)出(如免費基礎(chǔ)包:@fortawesome/free-solid-svg-icons、免費公司 logo 包:@fortawesome/free-brands-svg-icons),并使用 @fortawesome/fontawesome-svg-core 模塊的 library 方法導(dǎo)入到 vue 的運行環(huán)境中。
import { faVolumeUp, faPlay, faPause, } from "@fortawesome/free-solid-svg-icons"; import { faWeibo, faWeixin, } from "@fortawesome/free-brands-svg-icons"; library.add( faVolumeUp, faPlay, faPause, faWeibo, faWeixin );
但我再剛開始開發(fā)時只使用了基礎(chǔ)包,公司 logo 包是我在開發(fā)途中用到時才引入的,但這時 fortawesome 官方對整個庫進行了版本升級,具體功能并沒有什么改變,只是 fix 了一些 bug,版本號也只升級了一個小版本。
但在編譯時 library.add 這里報告了錯誤:
TS2345: Argument of type "IconDefinition" is not assignable to parameter of type "IconDefinitionOrPack". Type "IconDefinition" is not assignable to type "IconPack".`
經(jīng)過跟進發(fā)現(xiàn):
@forawesome/fontawesome-svg-core 的 library.add 的參數(shù)所要求的 IconDefinition 類型來自頂層 node_modules 安裝的公用的 @fortawesome/fontawesome-common-types 包的 index.d.ts 文件。
而 @fortawesome/free-brands-svg-icons 中字體的類型 IconDefinition 來自 @fortawesome/free-brands-svg-icons 自身內(nèi)部 node_modules 里安裝的高版本的 @fortawesome/fontawesome-common-types 的 index.d.ts 文件。
雖然兩個類型的定義一模一樣,但因為不是同一個文件定義的,所以是完全不同的兩種類型,因而造成了類型不匹配,無法正常編譯。
遇到這種問題時,升級對應(yīng)包的版本就可以了。
復(fù)雜泛型嵌套的生成方法與可讀性talk is cheap, show you the dunce.
節(jié)選自 vue/types/vue.d.ts,我已經(jīng)看暈了,調(diào)用方想要查錯的時候到底怎么看呢。
export interface VueConstructor泛型(嵌套) + 合并聲明 + 混入{ new (options?: ThisTypedComponentOptionsWithArrayProps ): CombinedVueInstance >; // ideally, the return type should just contains Props, not Record . But TS requires Base constructors must all have the same return type. new (options?: ThisTypedComponentOptionsWithRecordProps ): CombinedVueInstance >; new (options?: ComponentOptions ): CombinedVueInstance >; extend(options?: ThisTypedComponentOptionsWithArrayProps ): ExtendedVue >; extend(options?: ThisTypedComponentOptionsWithRecordProps ): ExtendedVue ; extend (definition: FunctionalComponentOptions , PropNames[]>): ExtendedVue >; extend (definition: FunctionalComponentOptions >): ExtendedVue ; extend(options?: ComponentOptions ): ExtendedVue ; nextTick(callback: () => void, context?: any[]): void; nextTick(): Promise set (object: object, key: string, value: T): T; set (array: T[], key: number, value: T): T; delete(object: object, key: string): void; delete (array: T[], key: number): void; directive( id: string, definition?: DirectiveOptions | DirectiveFunction ): DirectiveOptions; filter(id: string, definition?: Function): Function; component(id: string): VueConstructor; component (id: string, constructor: VC): VC; component(id: string, definition: AsyncComponent): ExtendedVue ; component(id: string, definition?: ThisTypedComponentOptionsWithArrayProps ): ExtendedVue >; component(id: string, definition?: ThisTypedComponentOptionsWithRecordProps ): ExtendedVue ; component (id: string, definition: FunctionalComponentOptions , PropNames[]>): ExtendedVue >; component (id: string, definition: FunctionalComponentOptions >): ExtendedVue ; component(id: string, definition?: ComponentOptions ): ExtendedVue ; use (plugin: PluginObject | PluginFunction , options?: T): void; use(plugin: PluginObject | PluginFunction , ...options: any[]): void; mixin(mixin: VueConstructor | ComponentOptions ): void; compile(template: string): { render(createElement: typeof Vue.prototype.$createElement): VNode; staticRenderFns: (() => VNode)[]; }; config: VueConfiguration; }
0 === san;
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/99185.html
摘要:解決問題當(dāng)我們在有限寬度的父級內(nèi)部時,如何創(chuàng)建一個全瀏覽器寬度的容器例子文字區(qū)域?qū)挾裙潭ň又袌D片全屏展示知道你們懶可直接復(fù)制看效果有限寬度的父容器無用文字幾分電視劇方了解到失聯(lián)飛機萊德斯基發(fā)了端上了電視劇方了解到失聯(lián)飛機淡藍色積分的 1. 解決問題 當(dāng)我們在有限寬度的父級內(nèi)部時,如何創(chuàng)建一個全瀏覽器寬度的容器? 2. 例子 2.1 文字區(qū)域 寬度固定 居中, 圖片 全屏展示 知道你們...
摘要:怎么影響了我的思考方式對前端開發(fā)者來說,能強化了面向接口編程這一理念。使用的過程就是在加深理解的過程,確實面向接口編程天然和靜態(tài)類型更為親密。摘要: 學(xué)會TS思考方式。 原文:TypeScript - 一種思維方式 作者:zhangwang Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 電影《降臨》中有一個觀點,語言會影響人的思維方式,對于前端工程師來說,使用 typescript 開...
摘要:怎么影響了我的思考方式對前端開發(fā)者來說,能強化了面向接口編程這一理念。使用的過程就是在加深理解的過程,確實面向接口編程天然和靜態(tài)類型更為親密。 電影《降臨》中有一個觀點,語言會影響人的思維方式,對于前端工程師來說,使用 typescript 開發(fā)無疑就是在嘗試換一種思維方式做事情。 其實直到最近,我才開始系統(tǒng)的學(xué)習(xí) typescript ,前后大概花了一個月左右的時間。在這之前,我也在...
摘要:特此寫個流水賬總結(jié),供自己以后羞恥的回顧。正逢月計劃辭職回家玩游戲過個暑假,結(jié)果在如今部門老大的忽悠下加入到了新東家。和組長兩人繼續(xù)沒晝夜的忙活,最終也按時交差,上了線。卷土重來,回報過去的一份念舊,期待的美好,個人選型入坑。 前言 2017年發(fā)生了太多的事情,結(jié)了婚,住進了新家,成功的播了種,當(dāng)上了準爸爸。公司也蒸蒸日上搬進了高大上的寫字樓。前端的坑越來越大,都來不及填。特此寫個流水...
閱讀 1509·2021-08-09 13:47
閱讀 2769·2019-08-30 15:55
閱讀 3492·2019-08-29 15:42
閱讀 1115·2019-08-29 13:45
閱讀 3009·2019-08-29 12:33
閱讀 1742·2019-08-26 11:58
閱讀 983·2019-08-26 10:19
閱讀 2411·2019-08-23 18:00