React & TypeScript

以前看了一下 TypeScript 的知識,可是一直沒有上手,最近開始結合 React 和 TypeScript 一塊兒嘗試了一下,感覺仍是很好的,因此寫一下筆記。css

環境配置沒有參考其餘東西,就是看了下 WebpackTypeScript 的官方文檔,使用 Webpack 進行構建仍是比較簡單的。html

環境構建

建立一個項目目錄,而後切換當前目錄到項目目錄下:node

$ mkdir tsc && cd ./tsc

而後使用 npm 初始化項目:react

$ npm init -y

而後建立一些項目文件:webpack

$ mkdir build src
$ touch build/webpack.base.conf.js build/webpack.dev.conf.js build/webpack.prod.conf.js index.html src/index.tsx tsconfig.json

接下來,就能夠安裝一些依賴了:es6

$ npm i webpack webpack-cli webpack-merge webpack-dev-server -D
$ npm i html-webpack-plugin clean-webpack-plugin typescript ts-loader style-loader css-loader @types/react @types/react-dom -D
$ npm i react react-dom -S

能夠注意到咱們沒有安裝 babel 轉譯器,若是咱們只寫 .ts 或者 .tsx 文件,能夠不安裝 babel。若是要轉譯處理 .js 文件的話,仍是要使用到 babel。web

咱們先寫基礎配置:typescript

webpack.base.conf.js
****npm

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: path.resolve(__dirname, '../src/index.tsx'),
  output: {
    filename: '[name].[hash].js'
  },
  resolve: {
    extensions: ['*', '.js', '.json', '.ts', '.tsx']
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new htmlWebpackPlugin({
      inject: true,
      template: path.resolve(__dirname, '../index.html')
    }),
    new cleanWebpackPlugin(['dist'])
  ]
};

而後能夠構造開發環境下的配置文件:編程

webpack.dev.conf.js
****

const merge = require('webpack-merge');
const path = require('path');
const baseConfig = require('./webpack.base.conf');

module.exports = merge(baseConfig, {
  mode: 'development',
  devtool: 'source-map',
  devServer: {
    port: 9999,
    open: true,
    contentBase: path.resolve(__dirname, '../dist')
  }
});

而後添加 npm 腳本到 package.json 中:

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "dev": "webpack-dev-server --config ./build/webpack.dev.conf.js"
}

而後添加咱們的 ts 配置到 tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",  // 打包輸出目錄
    "noImplicitAny": true,  // 默認必須爲變量指定類型
    "module": "es6", // 使用 ESM 模塊化方案
    "target": "es5", // 代碼編譯成 ES 5
    "jsx": "react", // 開啓 JSX,使用 react 方式編譯,若是要使用 babel 編譯,那就將 jsx 設置爲 ‘preserve’
    "allowJs": true, // 容許編譯 js 代碼
    "sourceMap": true,  // 編譯後同時產出 map 文件
    "removeComments": true // 移除註釋
  }
}

更多的配置項解釋,參考:翻譯 | 開始使用 TypeScript 和 React

寫完了之後咱們就能夠添加內容到咱們的開發文件中了:

index.html
****

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

src/index.tsx
****

import * as React from 'react';
import * as ReactDOM from 'react-dom';

ReactDOM.render(
  <h1>Hello TSX!</h1>,
  document.getElementById('root') as HTMLElement
);

能夠注意到引入 React 和 ReactDOM 的方式和以前有一些不一樣。
另外因爲 TypeScript 的強制轉換符 <> 和 JSX 的元素相沖突,因此使用 as 做爲強制轉換符。

運行 npm run dev,能夠查看效果。

使用 TypeScript 之後,項目配置要稍微簡單一點。配置好開發環境之後,就能夠寫代碼啦!

第一個組件

我以一個 Header 組件爲例,效果以下:

新建一個 Header.tsx 文件和一個 Header.css 文件到 src/components 下。

因爲頭部欄的標題文字應該是能夠修改的,而後右邊的 menu 應該是能夠自定義的,因此這些數據應該均可以經過 props 傳入咱們的 Header 組件。

寫咱們的 Header 組件:

// Header.tsx

// 引入 React
import * as React from 'react';
// 引入咱們的組件樣式
import './Header.css';

// 定義的接口,用於規範 Header 組件的 props,向外界公開,
// 便於在其餘組件中引用時實現這個接口,減小錯誤
export interface HeaderProps {
  title: string; // 必須給定 title,一個 string 類型的值
  menus?: MenuItemProps[];  // menus 是可選屬性,是一個符合 MenuItemProps 接口規範的對象的數組
  height?: string;  // 問號都表明可選項
  bgColor?: string;
}

// 這個接口定義了 MenuItem 組件的 props 規範,同時也定義了
// HeaderProps 中 menus 數組的元素的規範
interface MenuItemProps {
  name: string;  // 給定 menu 的名稱
  href: string;  // 給定 menu 要跳轉的連接
}

// 定義了 Header 組件的 state 的規範
interface HeaderState {
  isVisible: boolean // 表明 Header 組件是否可見
}

// Header 組件
// 注意 React.Component 後面的泛型,就是咱們上方定義的接口,它們分別制定了組件的 props 和 state 的規範
class Header extends React.Component<HeaderProps, HeaderState> {
  // 指定組件實例的 state,必須符合 HeaderState 的規範
  state = {
    isVisible: true
  }
  render() {
    const {
      title,
      menus = [],
      height = '50px',
      bgColor = 'lightblue'
    } = this.props;  // 從 props 獲取值,其中可選項都有默認值
    const style = {
      height,
      backgroundColor: bgColor
    };  // 構造 Header 內聯樣式
    return this.state.isVisible ? <div style={style} className="header">
      <span>{title}</span>
      <div className="header-menus">
        {
          menus.map(item => <MenuItem {...item}/>)
        }
      </div>
    </div> : null;
  }
}

// MenuItem 組件
// state 的規範是一個 object,未指定具體接口類型
class MenuItem extends React.Component<MenuItemProps, object> {
  render() {
    const { name, href } = this.props;
    return <a className="header-menu-item" href={href} key={href}>
      {name}
    </a>
  }
}

// 最後向外部暴露 Header 組件
export default Header;

能夠看到 TypeScript 結合 React 其實很好用,尤爲在規範 props 的時候很好用,可以避免不少編程時候的錯誤。而 IDE 的提示可以更加地方便咱們開發。寫起來何止舒服,簡直舒服啊~

而後在 Header.css 寫一下咱們的樣式:

html,
body,
div {
  margin: 0;
  padding: 0;
  font-size: 16px;
}

.header {
  font-size: 1.5rem;
  line-height: 1rem;
  padding: 1rem;
  box-sizing: border-box;
  position: relative;
}

.header-menus {
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
}

.header-menu-item {
  margin: 0 .5rem;
}

這裏僅僅是作個示例,排版沒有在乎太多的通用性,你們看看就好~

而後咱們就能夠在 index.tsx 中使用咱們的 Header 組件了:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Header, { HeaderProps } from './components/Header';  // 引入接口規範和組件


// 構造 Header 組件的 props,必須符合 HeaderProps 接口規範。
// 在寫的過程當中 IDE 也能給咱們不少的提示,方便了開發
const headerProps: HeaderProps = {
  title: 'Hello TSX!',
  menus: [{
    name: 'menu1',
    href: 'https://www.zhongdeming.fun'
  }, {
    name: 'menu2',
    href: 'https://www.baidu.com'
  }],
  bgColor: 'lightyellow'
};

ReactDOM.render(
  <Header {...headerProps}/>,
  document.getElementById('root') as HTMLElement
);

這樣一個組件就寫完了,能夠感覺到 TypeScript 確實可以加速咱們的開發,減小開發中的錯誤。

下面是一些利用 TypeScript 開發的時候 IDE 給出的提示的截圖:




相關文章
相關標籤/搜索