实现:
控制加载动图的两种方式
方式一:动态控制传入loading属性
方式二:在组件的componendDidMount回调中向外暴露了两个方法用来控制加载动图的出现/隐藏
传递参数:
color:PropTypes.string, 按钮背景颜色
height:PropTypes.string, 按钮高度
width:PropTypes.string, 按钮宽度
borderRadius:PropTypes.string, 按钮圆角
label:PropTypes.string, 按钮文本内容
iconName:PropTypes.string, 按钮图标,阿里iconfont中的iconfont类名称(无.前缀),前提当前项目已导入字体图标
plain:PropTypes.bool, 朴素模式,朴素模式下的颜色必须为16进制
borderColor:PropTypes.string, 边框颜色
labelColor:PropTypes.string, 按钮文本颜色
labelSize:PropTypes.string, 按钮文本大小
onClick:PropTypes.func, 按钮点击事件
disabled:PropTypes.bool, 禁用按钮
loading:PropTypes.bool, 开启动图加载按钮
onControl:PropTypes.func 控制动态加载图标的显示/隐藏,回调的第一个参数对象中包含loadingStart/loadingEnd方法
使用:
<Button onControl={this._onControl.bind(this)} onClick={this._onclick.bind(this)} iconName='icon-lajixiang' loading label={'测试内容'} color='#4608AD'></Button>
效果图:
普通按钮:
朴素按钮:
图标按钮:
动态加载按钮:
代码示例:
button.jsx:
import React,{Component} from 'react';
import PropTypes from 'prop-types';
import './button.css'
class App extends Component{
static propTypes={
color:PropTypes.string,
height:PropTypes.string,
width:PropTypes.string,
borderRadius:PropTypes.string,
label:PropTypes.string,
iconName:PropTypes.string,
plain:PropTypes.bool, //朴素模式下的颜色必须为16进制
borderColor:PropTypes.string,
labelColor:PropTypes.string,
labelSize:PropTypes.string,
onClick:PropTypes.func,
disabled:PropTypes.bool,
loading:PropTypes.bool,
onControl:PropTypes.func
}
static defaultProps={
label:'默认内容',
color:'#409EFF',
labelColor:'white',
height:'40px',
width:'100px',
borderRadius:'5px',
labelSize:'16px',
borderColor:'transparent'
}
state={
className:['jf-button-container'],
plainFlag:false, //朴素模式下的移入移出情况
loadingFlag:true //控制加载图案显示
}
//进制转换成rgba
hexToRgba(hex, opacity=0.2) {
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return `rgba(${parseInt(result[1], 16)},${parseInt(
result[2],
16
)},${parseInt(result[3], 16)},${opacity})`;
}
getColor(color)
{
if(this.props.plain)
{
return this.hexToRgba(color)
}
return color;
}
componentDidMount()
{
if(this.props.loading)
{
this.props.onControl({loadingStart:this._loadingStart,loadingEnd:this._loadingEnd});
}
if(this.props.disabled)
{
this.state.className.push('jf-button-container-disabled')
this.setState({
className:this.state.className
})
}
}
//朴素模式下的样式设置
_mouseover(e)
{
if(this.props.plain)
{
this.setState({
plainFlag:true
})
}
}
_mouseout(e)
{
if(this.props.plain)
{
this.setState({
plainFlag:false
})
}
}
//关闭/开启加载图即动画
_loadingStart=()=>
{
this.setState({
loadingFlag:true
})
}
_loadingEnd=()=>
{
this.setState({
loadingFlag:false
})
}
render()
{
let {color,loading,iconName,labelColor,height,width,borderRadius,borderColor,label,plain,labelSize,onClick,disabled} =this.props;
let {className,plainFlag,loadingFlag}=this.state
//朴素模式下的样式设置
if(plain)
{
if(plainFlag&&!disabled)
{
labelColor='white';
borderColor=color;
}else{
labelColor=color;
borderColor=color;
color=this.getColor(color);
}
}
return(
<div onMouseOver={this._mouseover.bind(this)} onMouseOut={this._mouseout.bind(this)} className={className.join(" ")} style={{borderColor,height,width,backgroundColor:color,borderRadius,}}>
<button disabled={disabled} onClick={onClick} className='jf-button ' style={{color:labelColor,fontSize:labelSize}}><span className={`iconfont ${iconName} ${loading&&loadingFlag&&'iconfont-loading'} ${loading&&loadingFlag&&'icon-jiazai'} `}></span>{label}</button>
</div>
)
}
}
export default App
button.css:
.jf-button-container{
display: flex;
height: 40px;
width: 100px;
background-color: red;
position:relative;
border-radius: 5px;
border: solid 1px red;
z-index: 99;
cursor: pointer;
}
.jf-button-container:hover{
opacity: .7;
}
.jf-button-container-disabled{
cursor: not-allowed;
opacity: .7;
}
.jf-button{
height: 100%;
width: 100%;
border: none;
background-color: transparent;
outline: none;
color: white;
cursor: inherit;
font-size: 16px;
z-index: -1;
}
.iconfont{
margin-right: 5px;
}
.iconfont-loading{
display: inline-block;
animation: rotate 2s linear infinite;
transform-origin: center;
}
@keyframes rotate{
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}