Typescript 入門構建一個 react 元件
阿新 • • 發佈:2018-11-08
TypeScript 入門,寫一個 react 進度條元件
寫在最前面
- 如果你寫過 react 的元件, 這篇文章對與你來說基本沒有什麼難度。純粹的是加上了一點 ts 的知識。
- 我完全是以學習者的姿態來描述我寫元件的過程,很多不嚴謹的地方請大家指出來哈哈。
看看實現的效果-gif 動圖效果
- 當然你可以點選這裡親自試一下效果,效果頁面
- 也可以開啟下面 codeSandbox 看一下原始碼(這玩意可能需要梯子)。
開始動手
-
這是一個普通的 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>
);
複製程式碼
大功告成
- 是不是很簡單,然我們再來看看效果
- codesandbox.io/s/940nq3531… ,除錯一下程式碼