TypeScript 入门,写一个 react 进度条组件
/*
* @param step 第几步
* @param total 总共的步骤
* @param showInfo 是否需要显示百分比提示
* @param color 可以自定义颜色
*/
-- componments
-- progressBar
-- index.tsx
-- style.less
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 是代表这个接口参数支持。
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'
};
render(){
return(
<div>progressBardiv>
)
}
}
复制代码
为什么用了 ts 和还用 prop-types?
去约束代码,文章发出以后就有朋友指出这样重复了。因为刚开始写 ts 也万全没注意到,然后着重的去查阅了相关资料。发现是可以混用的这两者。
可以只用typescript进行验证,也可以只用prop-types进行验证,也可以两者混搭进行验证,这个并没用严格限制。用typescript验证提示是ts语言带来的功能,用prop-types验证提示是react带来的功能。
要点
: 其中的“ ?”表示可选,number 就是接口参数的类型。表示你输入的必须是一个 number 类型,不然 ts 会报错。这里我们可以引用一下 progressBar 模块,看看成功没有。如果现实了 progressBar 的话就表示成功了。
/**
* @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 中处理数据。 进度条的实现很多种,这里就是普通的三层,文字,背景,进度条,和外层。
.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 背景作为总的长度。
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>
);
复制代码
ts
还去使用 prop-types
?react
组件的时候,我们会去定义一个 prop-types
去校验我们的 class
的参数输入。而 ts 的 interface
的作用当然也是校验 props
的输入。
两者的区别
:TypeScrip
· 的类型检查是静态的,prop-types
可以在运行时进行检查。你如你传了个offsetTop="abc"
,你的编辑器可能会提示你类型有误,但是在浏览器里仍然是可以正常运行的。而如果你使用了 prop-types
,在浏览器里就会给出提示。
总结: 所以两者是可以混用的,
功能上有部分重复
, 所以我们使用了 typescript 以后完全可以不写prop-types
来做额外的校验了。