一、相關(guān)環(huán)境搭建
1.安裝typescript以及用到的第三方庫的聲明文件
npm install --save typescript @types/node @types/react @types/react-dom @types/jest @types/react-router-dom
2.針對ts、tsx文件我們需要通過babel-loade以及ts-loader編譯
npm install babel-loader ts-loader --save -dev
ts-loader可以讓W(xué)ebpack使用TypeScript的標(biāo)準(zhǔn)配置文件tsconfig.json編譯TypeScript代碼。
如果webpack為4.x以下版本,ts-loader只能安裝3.x版本,因?yàn)楦甙姹镜膖s-loade僅支持webpack4.x版本
npm install ts-loader@3
webpack.config.js文件添加配置如下內(nèi)容:
module: {
rules: [
{
test: /\.tsx?$/,
use: ['babel-loader', 'ts-loader'],
exclude: /node_modules/,
} ]
},
resolve:{
extensions: ['.js', '.jsx','.tsx', '.ts'] //引入文件時(shí)無需加以上后綴
}
在低版本webpack中進(jìn)行配置,若webpack運(yùn)行時(shí)拋出一個(gè)錯(cuò)誤:
TypeError: element.loader.split is not a function
原來是loader期待的一個(gè)字符串,而這里明顯是一個(gè)數(shù)組,數(shù)組沒有split方法:
//修改前
loaders: [
{ test: /\.(ts|tsx)$/,loader:['babel-loader', 'ts-loader'],exclude: /node_modules/}
]
//修改后
loaders: [
{ test: /\.(ts|tsx)$/,loaders:['babel-loader', 'ts-loader'],exclude: /node_modules/},
{ test: /\.(js|jsx)$/, loader: "jsx!babel", include: /src/ ,exclude: /node_modules/},
{ test: /\.css$/, loader: ExtractTextPlugin.extract("css", "css!postcss") },
{ test: /\.scss$/, loader: ExtractTextPlugin.extract("css", "css!postcss!sass!sass-resources") },
{test: /\.less$/, loader: ExtractTextPlugin.extract('css','css!postcss!less')},
{ test: /\.(png|jpg)$/, loader: 'url?limit=8192&name=images/[hash:8].[name].[ext]' }
]
3.添加TypeScript配置文件 ,在當(dāng)前根目錄下創(chuàng)建tsconfig.json文件,并添加如下內(nèi)容:
{
"compilerOptions": {
"module": "esnext",
"target": "es6",
"allowSyntheticDefaultImports": true,
// import的相對起始路徑
"baseUrl": ".",
"sourceMap": true,
// 構(gòu)建輸出目錄,但因?yàn)槭褂昧薫webpack`,所以這個(gè)配置并沒有什么卵用
"outDir": "../client-dist",
// 開啟`JSX`模式,
// `preserve`的配置讓`tsc`不會去處理它,而是使用后續(xù)的`babel-loader`進(jìn)行處理
"jsx": "preserve",
"strict": true,
"moduleResolution": "node",
// 開啟裝飾器的使用
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
// `vs code`所需要的,在開發(fā)時(shí)找到對應(yīng)的路徑,真實(shí)的引用是在`webpack`中配置的`alias`
"paths": {
"@Common": [
"../src/common"
],
"@Common/*": [
"../src/common/*"
]
}
},
"exclude": [
"node_modules"
]
}
開啟typescript代碼校驗(yàn)的相關(guān)設(shè)置可以參看上篇文章
二、在React項(xiàng)目中使用TypeScript
在 react 中使用 ts 的幾點(diǎn)變化
- 文件以tsx后綴命名
- 使用組件聲明時(shí)的Component<P, S>泛型參數(shù)聲明,來代替PropTypes
- 全局變量或者自定義的window對象屬性,統(tǒng)一在項(xiàng)目根目錄下的global.d.ts中進(jìn)行聲明定義
- 對于項(xiàng)目中常用到的接口數(shù)據(jù)對象,可以在types/目錄下定義好其結(jié)構(gòu)化類型聲明
1.類組件的聲明
/*定義屬性props的類型 */
interface Iprops{
chooseBrandSeries:(clickBrand:string, brandText:string, clickSeries:any, seriesText:string)=>void //在 TypeScript 的類型定義中,=> 用來表示函數(shù)的定義,左邊是輸入類型,需要用括號括起來,右邊是輸出類型。
}
/*定義狀態(tài)機(jī)state的類型 */
interface Istate{
currentIndex: number, //控制品牌篩選項(xiàng)的選中樣式
seriesIndex: number, //控制車系篩選項(xiàng)的選中樣式
brandLists: any[], //品牌篩選項(xiàng)
isShow: boolean, //控制車系篩選項(xiàng)的展示
chexi: any[], //車系篩選項(xiàng)
clickBrand: string, //用于存儲選中的品牌信息,如"408844",
brandText: string, //用于存儲選中的品牌名
clickSeries: string, //用于存儲選中的車系信息,如"409052"
seriesText: string, //用于存儲選中的車系名
index: string
}
export default class ScrollList extends React.Component<Iprops,Istate> {
constructor(props:Iprops) {
super(props);
}
private loadMoreTimer:any;
state:Istate={
flag: false
}
}
有了 Typescript 之后可以安全地約束 Props 和 State, 沒有必要引入 React.PropTypes, 而且它的表達(dá)能力比較弱
TypeScript 可以使用三種訪問修飾符(Access Modifiers),分別是 public、private 和 protected
- public 修飾的屬性或方法是公有的,可以在任何地方被訪問到,默認(rèn)所有的屬性和方法都是 public 的
- private 修飾的屬性或方法是私有的,不能在聲明它的類的外部訪問
- protected 修飾的屬性或方法是受保護(hù)的,它和 private 類似,區(qū)別是它在子類中也是允許被訪問的