- 如果你写过 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> ); 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【译】如何专业的构建Vue组件
- [译] 使用 Recompose 来构建高阶组件
- 怎样才能构建优秀的React组件?
- 如何构建运行良好的Vue组件
- 如何构建一个简单的摄像头组件
- (译)Vue.js 构建一个"无渲染"组件
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。