Typescript結合React實踐

文章首發於:github.com/USTB-musion…前端

寫在前面

Typescript是JavaScript的一個超集,主要提供了類型系統和對es6的支持。本人使用ts編寫react將近3個月的時間,中間踩了很多坑,從剛開始的以爲ts沒有必要到如今以爲ts真香。在這裏對使用ts編寫react的心得作一下總結。react

本文將從如下幾部分進行總結:git

  1. Typescript的優點
  2. TS結合React使用
  3. 總結
  4. 參考連接及擴展閱讀

Typescript的優點

1.幫助更好地重構代碼

一個好的代碼習慣是經常對本身寫的代碼進行小的重構,使得代碼可維護性更強。可是對於不少線上運行的代碼,代碼測試覆蓋率每每不是很高,有時候哪怕一個變量名的改動,都會牽一髮而動全身。而對於使用ts編寫的項目就不會有這種擔憂。ts的靜態檢查特性會幫助找出代碼中有錯誤的部分。es6

2.vscode等IDE的提示更加智能

js是一門動態弱類型解釋語言,變量聲明後能夠改變類型,並且類型須要在運行時才能肯定。而ts的報錯提示是在編譯時,不是在運行時。因此使用ts帶來的靜態類型檢查等特性將使得IDE的提示更加完善。github

3.類型聲明自己就是很是好的文檔

當你接手一個有歷史包袱的項目時,確定會頭疼於文檔和代碼註釋的缺失,而對於ts來講,是能夠作到代碼即文檔的,經過聲明文件能夠知道哪些字段的含義以及哪些字段是必填和選填的。舉個簡單例子,當封裝一個button的組件時:typescript

export interface ButtonProps {
  style?: React.CSSProperties
  className?: string
  label?: React.ReactNode
  type?: 'primary' | 'default' | 'search'
  size?: 'sm' | 'md' | 'lg' | 'mini'
  disabled?: boolean
  title?: string
  onClick?: ((e: React.MouseEvent<HTMLButtonElement>) => void)
}
複製代碼

經過這些聲明文件能夠知道,當使用這個button文件時,style是一個可選值,表示一個能夠自定義樣式的style字段。type也是一個可選值,表示按鈕的顏色類型,能夠選擇'primary','default','mini'其中的一種。disabled也是一個可選值,傳入的值必須是boolean類型。因此就能夠看出類型聲明自己就是很是好的文檔。bash

TS結合React使用

類組件的使用

如下是官網的一個例子,建立Props和State接口,Props接口接受name和enthusiasmLevel參數,State接口接受currentEnthusiasm參數。less

import * as React from "react";

export interface Props {
  name: string;
  enthusiasmLevel?: number;
}

interface State {
  currentEnthusiasm: number;
}

class Hello extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { currentEnthusiasm: props.enthusiasmLevel || 1 };
  }

  onIncrement = () => this.updateEnthusiasm(this.state.currentEnthusiasm + 1);
  onDecrement = () => this.updateEnthusiasm(this.state.currentEnthusiasm - 1);

  render() {
    const { name } = this.props;

    if (this.state.currentEnthusiasm <= 0) {
      throw new Error('You could be a little more enthusiastic. :D');
    }

    return (
      <div className="hello">
        <div className="greeting">
          Hello {name + getExclamationMarks(this.state.currentEnthusiasm)}
        </div>
        <button onClick={this.onDecrement}>-</button>
        <button onClick={this.onIncrement}>+</button>
      </div>
    );
  }

  updateEnthusiasm(currentEnthusiasm: number) {
    this.setState({ currentEnthusiasm });
  }
}

export default Hello;

function getExclamationMarks(numChars: number) {
  return Array(numChars + 1).join('!');
}

複製代碼

無狀態組件的使用

無狀態組件也稱爲傻瓜組件,若是一個組件內部沒有自身的state,那麼組件就能夠稱爲無狀態組件。在@types/react已經定義了一個類型type SFC<P = {}> = StatelessComponentpost

。咱們寫無狀態組件的時候,能指定咱們的組件爲SFC或StatelessComponent。它已經預約義了children,displayName等。 以button爲例:學習

import React from 'react'

const Button = ({ onClick: handleClick, children }) => (
  <button onClick={handleClick}>{children}</button>
)
複製代碼

若是採用ts來編寫出來的無狀態組件是這樣的:

import React, { MouseEvent, SFC } from 'react';

type Props = { onClick(e: MouseEvent<HTMLElement>): void };

const Button: SFC<Props> = ({ onClick: handleClick, children }) => (
  <button onClick={handleClick}>{children}</button>
);
複製代碼

readonly

react規定不能經過this.props.xxx和this.state.xxx直接進行修改,因此能夠將State和Props標記爲不可變數據:

interface Props {
  readonly number: number;
}

interface State {
  readonly color: string;
}

export class Hello extends React.Component<Props, State> {
  someMethod() {
    this.props.number = 123; // Error: props 是不可變的
    this.state.color = 'red'; // Error: 你應該使用 this.setState()
  }
}
複製代碼

處理Event對象

在工做中,可能常常會使用Event對象,change事件可使用React.ChangeEvent, click事件可使用React.ChangeEvent。

onClick = (e: React.MouseEvent<HTMLButtonElement>) => {
      // do something
  }
  
  onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      // do something
  }
複製代碼

可渲染的接口

React 能夠渲染一些像 JSX 或者是 string 的內容,這些被合併到類型 React.ReactNode 中,所以,當你接收可渲染的內容時,你可使用它:

type Props = {
  header: React.ReactNode;
  body: React.ReactNode;
};

class MyComonent extends React.Component<Props, {}> {
  render() {
    return (
      <div>
        {this.props.header}
        {this.props.body}
      </div>
    );
  }
}

<MyComponent header={<h1>Header</h1>} body={<i>body</i>} />
複製代碼

總結

在大中型前端項目中,因爲js的動態弱類型特性,致使不少錯誤在運行時才發現。ts做爲js的超集,爲前端開發帶來了編譯時的檢查,將不少的錯誤避免在了編譯階段。也爲IDE帶來了更強的智能提示。雖然學習ts會花一些時間,但這些時間是值得的。使用ts開發項目以後,明顯發現項目的可維護性變強了,bug率下降了,查文檔也更加方便,一看類型聲明文件就明白了各個字段的含義。

參考連接及擴展閱讀

TypeScript 2.8下的終極React組件模式

深刻理解 TypeScript

TypeScript-React-Starter

相關文章
相關標籤/搜索