1. 程式人生 > >Typescript 入門構建一個 react 元件

Typescript 入門構建一個 react 元件

TypeScript 入門,寫一個 react 進度條元件

寫在最前面

  • 如果你寫過 react 的元件, 這篇文章對與你來說基本沒有什麼難度。純粹的是加上了一點 ts 的知識。
  • 我完全是以學習者的姿態來描述我寫元件的過程,很多不嚴謹的地方請大家指出來哈哈。

看看實現的效果-gif 動圖效果

image

  • 當然你可以點選這裡親自試一下效果,效果頁面
  • 也可以開啟下面 codeSandbox 看一下原始碼(這玩意可能需要梯子)。
Edit 940nq3531y

開始動手

  • 這是一個普通的 UI 元件,難點主要在設計(css)上面。

  • 需求:分步驟進行的一個精度條,我們只需要輸入引數,step 和 total 來計算出百分比然後顯示就 ok 了。


/*
* @param step 第幾步
* @param total 總共的步驟
* @param showInfo  是否需要顯示百分比提示
* @param color 可以自定義顏色
*/

複製程式碼

說了這麼多開始動手吧

  • 環境配置方面就略過了,這裡我們直接來寫程式碼

  • 需要配置 node,ts,less 環境

  • 1、在你的 componments 檔案下建立一個 progressBar 資料夾。tsx 是 react下特殊 ts 檔案。 然後在 progressBar 下面繼續新增 index.tsx 和 style.less

-- componments
    -- progressBar
        -- index.tsx
        -- style.less
複製程式碼

index.tsx

  • 2、先引進必須的元件
import React, { Component } from 'react';
import * as PropTypes from 'prop-types';
import './style.less';

// 定義介面 
export interface IProgressProps{
    
}

// 定義類
class ProgressBar extends Component<IProgressProps> {

}

export default ProgressBar;

複製程式碼

要點: IProgressProps ,使用 pascal 命名,用 I

打頭,Props 是代表這個介面引數支援。

  • 3、根據我們上面需求的分析,我們來定義 interface,定義類的 propTypes 和 defalutProps
export interface IProgressProps {
    // prefixCls 為了以後樣式統一設定的 classname
    
    prefixCls?: string;
    step?: number;
    total?: number;
    showInfo?: boolean;
    color?: string;
}

class ProgressBar extends Component<IProgressProps> {
    //設定預設值
    static defaultProps = {
            prefixCls: 'demo-progress',
            step: 2,
            total: 10,
            showInfo: false,
            color: '#FFE103'
        };
    //設定類的引數型別
    static propTypes = {
        prefixCls:PropTypes.string,
        step: PropTypes.number,
        total: PropTypes.number,
        showInfo: PropTypes.bool,
        color: PropTypes.string
    };
    
    render(){
        return(
            <div>progressBar</div>
        )
    }
}
複製程式碼

要點: 其中的“ ?”表示可選,number 就是介面引數的型別。表示你輸入的必須是一個 number 型別,不然 ts 會報錯。這裡我們可以引用一下 progressBar 模組,看看成功沒有。如果現實了 progressBar 的話就表示成功了。

  • 4、處理進度條 UI 和文字內容,render部分
/**
 * @desc  處理 progressNumber
 */
const validProgress = (progress: number | undefined) => {
  //當你的引數定義了 number 等型別,你必須對 !progress 的時候處理,不然 ts 會提示你錯誤。
  if (!progress || progress < 0) {
    return 0;
  } else if (progress > 100) {
    return 100;
  }

  return progress;
};

/**
 * @desc 除法處理成0-100的整數
 * @param step
 * @param total
 */
const percentDeal = (step: number | undefined, total: number | undefined) => {
  if (!step || !total) {
    return 0;
  }

  return (step / total) * 100;
};

/**
 * @param text 百分比顯示
 */
const parseIntPrecent = (text: number): string => `${Math.ceil(text)}%`;

class ProgressBar extends Component<IProgressProps> {
   /* ...
    ....defaultProps
    .....propTypes
    ......
   */
    render(){
        // 把需要的值先從 this.props 中取出來
        // restProps 擴充引數用
        const {
            prefixCls,
            step,
            total,
            showInfo,
            color,
            ...restProps
        } = this.props;
        
        /**
         * percent 百分比
         * text tip 顯示文字
         * progressInfo 提示模組
         * porgress 主模組
         */
        let percent;
        let text;
        let progressInfo;
        let progress;
        
        //處理百分比顯示內容
        percent = percentDeal(step, total);
        text = parseIntPrecent(validProgress(percent));
        
        // 如果 true 的話,我們使用建立一個 showInfo 模組
        if (showInfo) {
            progressInfo = (
                <div className={`${prefixCls}-show-info`}>
                  <span className={`${prefixCls}-text`}>{text}</span>
                </div>
            );
        }
        
        //建立一個主模組用做進度條
        //prefixCls 這裡統一了命名
        progress = (
          <div>
            <div className={`${prefixCls}-outer`}>
              <div className={`${prefixCls}-inner`}>
                <div className={`${prefixCls}-bg`}>
                  {progressInfo || null}
                </div>
              </div>
            </div>
          </div>
        );
        
        return (
          <div {...restProps} className={`${prefixCls}`}>
            {progress}
          </div>
        );
    }
}
複製程式碼

要點:把處理資料的函式定義在 class 外部,不要在 render 中處理資料。 進度條的實現很多種,這裡就是普通的三層,文字,背景,進度條,和外層。

style.less

  • 5、根據上面的 gif 設計圖來實現一下樣式
.tiger-progress {
    &-outer {
        width: 100%;
        display: inline-block;
        margin-top:30px;
        margin-right: 0;
        padding-right: 0;
    }
    &-inner {
        vertical-align: middle;
        display: inline-block;
        background: #eeeeee;
        border-radius: 100px;
        position: relative;
        width: 100%;
    }
//預留 &-bg 背景顏色代表進度條的長度,灰色的 inner 背景
    &-line {
        width: 100%;
        font-size: inherit;
        position: relative;
    }
    &-text {
        word-break: normal;
        width: 2em;
        text-align: left;
        font-size: 1em;
        margin-left: 8px;
        vertical-align: middle;
        display: inline-block;
        white-space: nowrap;
        line-height: 1;
    }
}
複製程式碼

要點:// &-bg 顏色代表進度條的長度,灰色的 &-inner 背景作為總的長度。

  • 補充 render 內的程式碼, 根據輸入的 step 和 total 計算出來的資料來設定一下進度條的長度。
 const {
        prefixCls,
        step,
        total,
        showInfo,
        color,
        ...restProps
    } = this.props;
        
/**
 * percent 百分比
 * text tip 顯示文字
 * progressInfo 提示模組
 * porgress 主模組
 */
let percent;
let text;
let progressInfo;
let progress;

percent = percentDeal(step, total);
console..log("percent",percent)
// percent: 20

text = parseIntPrecent(validProgress(percent));
console.log('text',text)
// text: 20%

if (showInfo) {
  progressInfo = (
    <div className={`${prefixCls}-show-info`}>
      <span className={`${prefixCls}-text`}>{text}</span>
    </div>
  );
}

// color defalutProps 定義預設的顏色
// 前面&-bg 設定 relative 定位
const fixBgStyle = {
  width: text,
  height: "12px",
  background: color,
  borderRadius: "100px"
};

progress = (
  <div>
    <div className={`${prefixCls}-outer`}>
      <div className={`${prefixCls}-inner`}>
        <div className={`${prefixCls}-bg`} style={fixBgStyle}>
          {progressInfo || null}
        </div>
      </div>
    </div>
  </div>
);

return (
  <div {...restProps} className="tiger-progress">
    {progress}
  </div>
);

複製程式碼

大功告成

參考