动画:
选择按钮旋转
下拉框伸缩
边框、图标、选项hover变色
参数:
placeholder:PropTypes.string, 预展示内容,不写则默认展示传入的list数组第一条内容
selectWidth:PropTypes.string, 展示框的宽度
fontSize:PropTypes.string, 展示框内的字体大小
selectHeight:PropTypes.string, 展示框的高度
borderColor:PropTypes.string, 展示框的边框色
hoverBoderColor:PropTypes.string,展示框hover时的边框色
borderRadius:PropTypes.string, 展示框的圆角
iconWidth:PropTypes.string, 图标的宽度
iconSize:PropTypes.string, 图标的大小
padding:PropTypes.string, 展示框内的内容距离左边的距离
selectListHeight:PropTypes.string, 下拉框的高度
selectListRadius:PropTypes.string, 下拉框的圆角
selectListWidth:PropTypes.string, 下拉框的宽度
selectListLeft:PropTypes.string, 下拉框距离左边的距离
selectListBoderColor:PropTypes.string, 下拉框的边框色
selectListFontSize:PropTypes.string, 下拉框的字体大小
selectListPadding:PropTypes.string, 下拉框的内容距离左边间距
selectTriangleWidth:PropTypes.string, 下拉框上的三角的大小
list:PropTypes.array, 下拉框展示的数组内容
onSelect:PropTypes.func, 选择回调,第一个参数是内容,如果不传入placeholder,默认就会触发一次
效果图:
代码示例:
使用:
import React,{Component} from 'react'
import Select from './select/select'
class App extends Component{
_onSelect(item)
{
console.log(item);
}
render()
{
return(
<div>
<Select list={['a','b','c']} placeholder='请选择' onSelect={this._onSelect.bind(this)}></Select>
<Select list={['a','b','c']} onSelect={this._onSelect.bind(this)}></Select>
<Select list={['a','b','c']} placeholder='请选择' onSelect={this._onSelect.bind(this)} disabled></Select>
</div>
)
}
}
export default App
select.jsx:
import React,{Component} from 'react'
import PropTypes from 'prop-types'
import './select.css'
class App extends Component{
static propTypes={
placeholder:PropTypes.string,
selectWidth:PropTypes.string,
fontSize:PropTypes.string,
selectHeight:PropTypes.string,
borderColor:PropTypes.string,
hoverBoderColor:PropTypes.string,
borderRadius:PropTypes.string,
iconWidth:PropTypes.string,
iconSize:PropTypes.string,
padding:PropTypes.string,
selectListHeight:PropTypes.string,
selectListRadius:PropTypes.string,
selectListWidth:PropTypes.string,
selectListLeft:PropTypes.string,
selectListBoderColor:PropTypes.string,
selectListFontSize:PropTypes.string,
selectTriangleWidth:PropTypes.string,
selectListPadding:PropTypes.string,
list:PropTypes.array,
onSelect:PropTypes.func,
}
static defaultProps={
list:[]
}
componentDidMount()
{ const {list,placeholder,fontSize,selectWidth,selectHeight,borderColor,borderRadius,hoverBoderColor,iconWidth,iconSize,padding,
selectListHeight,selectListRadius,selectListWidth,selectListLeft,selectListBoderColor,selectListFontSize,selectTriangleWidth,selectListPadding
} = this.props;
const selectf=this.selectf.style;
(list.length)&&this.setState({
selectList:list,
inputValue:placeholder?'':list[0]
},()=>{
!placeholder&&this._filter(this.state.inputValue);
!placeholder&&this._onSelected(this.state.inputValue,0);
})
selectWidth&&selectf.setProperty('--selectWidth',selectWidth);
fontSize&&selectf.setProperty('--fontSize',fontSize);
selectHeight&&selectf.setProperty('--selectHeight',selectHeight);
borderColor&&selectf.setProperty('--borderColor',borderColor);
borderRadius&&selectf.setProperty('--borderRadius',borderRadius);
hoverBoderColor&&selectf.setProperty('--hoverBoderColor',hoverBoderColor);
iconWidth&&selectf.setProperty('--iconWidth',iconWidth);
iconSize&&selectf.setProperty('--iconSize',iconSize);
padding&&selectf.setProperty('--padding',padding);
selectListHeight&&selectf.setProperty('--selectListHeight',selectListHeight);
selectListRadius&&selectf.setProperty('--selectListRadius',selectListRadius);
selectListWidth&&selectf.setProperty('--selectListWidth',selectListWidth);
selectListLeft&&selectf.setProperty('--selectListLeft',selectListLeft);
selectListBoderColor&&selectf.setProperty('--selectListBoderColor',selectListBoderColor);
selectListFontSize&&selectf.setProperty('--selectListFontSize',selectListFontSize);
selectTriangleWidth&&selectf.setProperty('--selectTriangleWidth',selectTriangleWidth);
selectListPadding&&selectf.setProperty('--selectListPadding',selectListPadding);
}
state={
isChecked:false,
inputValue:'',
selectList:[],
}
_onChecked()
{
if(!this.props.disabled)
{
this.setState({
isChecked:!this.state.isChecked
})
}
}
_onSelected(item)
{
this.setState({inputValue:item,isChecked:false});
this._filter(item);
this.props.onSelect(item);
}
_filter(name)
{
let arr=this.props.list.filter((item,index)=>{
return name!=item
})
this.setState({
selectList:arr
});
}
render()
{
const {isChecked,inputValue,selectList} = this.state;
const {disabled,placeholder}=this.props;
return(
<div className='jf-select-container' ref={(v)=>{this.selectf=v;}}>
<input disabled={disabled} value={inputValue} placeholder={placeholder} className={`jf-select-inner ${!disabled&&'jf-select-inner-notDisabled'} ${disabled&&'jf-select-disabled'}`} type="text" readOnly/>
<span onClick={this._onChecked.bind(this)} className={`jf-select-inner-icon iconfont ${!disabled&&'jf-select-inner-icon-notDisabled'} ${disabled&&'jf-select-disabled'} icon-xiasanjiao ${isChecked&&'jf-select-inner-icon-selected'}`}></span>
<div className={`jf-select-list-container ${isChecked?'jf-select-list-container-show':'jf-select-list-container-hide'} `}>
<div className='jf-select-list'>
<div className='jf-select-list-triangle'></div>
<ul className='jf-select-list-ul'>
{
selectList.map((item,index)=>{
return <li onClick={()=>{this._onSelected(item)}} key={item+index}>{item}</li>
})
}
</ul>
</div>
</div>
</div>
)
}
}
export default App
select.css:
.jf-select-container{
width: var(--selectWidth);
height:var(--selectHeight);
display: inline-block;
/* background-color: red; */
box-sizing: border-box;
margin-left: 5px;
border-radius: var(--borderRadius);
position: relative;
--selectWidth:240px;
--fontSize:16px;
--selectHeight:40px;
--borderColor:#ccc;
--hoverBoderColor:#aaa;
--borderRadius:5px;
--cursor:pointer;
--iconWidth:40px;
--iconSize:16px;
--padding:5%;
--selectListHeight:200px;
--selectListRadius:5px;
/* --selectListWidth:240px; */
/* --selectListPadding */
--selectListLeft:0px;
--selectListBoderColor:#ccc;
--selectListFontSize:16px;
--selectTriangleWidth:6px;
}
.jf-select-disabled{
cursor: not-allowed !important;
background-color: #F5F7FA;
}
.jf-select-inner{
width: 100%;
height: 100%;
outline: none;
box-sizing: border-box;
border:solid 1px var(--borderColor);
cursor: var(--cursor);
border-radius: var(--borderRadius);
padding-left: var(--padding);
font-size: var(--fontSize);
padding-right: var(--iconWidth);
overflow: hidden;
text-overflow: ellipsis;
}
.jf-select-inner-notDisabled:hover{
border-color: var(--hoverBoderColor);
}
.jf-select-inner-icon{
position: absolute;
height: 90%;
display:flex;
justify-content: center;
align-items: center;
width:var(--iconWidth);
margin: 0;
top:50%;
transform: translateY(-50%) rotate(0deg);
right: 2px;
color:var(--borderColor);
cursor:var(--cursor);
box-sizing: border-box;
font-size: var(--iconSize);
transition:transform .25s;
z-index: 10;
}
.jf-select-inner-icon-selected{
transform:translateY(-50%) rotate(-180deg);
}
.jf-select-inner-icon-notDisabled:hover{
color:var(--hoverBoderColor);
}
.jf-select-list-container{
position: absolute;
box-sizing: border-box;
width: var(--selectListWidth,var(--selectWidth));
height:0;
opacity: 0;
top: 110%;
left:var(--selectListLeft);
margin: 0;
display: flex;
transition: height .5s,opacity .5s;
}
.jf-select-list-container-show{
height: var(--selectListHeight);
opacity: 1;
}
.jf-select-list{
width: 100%;
height: 100%;
position: relative;
display: flex;
}
.jf-select-list-triangle{
position: absolute;
top:0;
left:var(--padding) ;
height: 0;
width: 0;
border-top-width: 0px;
border-right-width:var(--selectTriangleWidth,6px);
border-bottom-width: var(--selectTriangleWidth,6px);
border-left-width:var(--selectTriangleWidth,6px);
border-style: solid;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: transparent;
border-bottom-color:var(--selectListBoderColor);
}
.jf-select-list-triangle::after{
content: '';
position: absolute;
left: 0;
top: 1px;
margin-left: calc(-1 * var(--selectTriangleWidth,6px));
border-top-width: 0px;
border-right-width:var(--selectTriangleWidth,6px);
border-bottom-width: var(--selectTriangleWidth,6px);
border-left-width:var(--selectTriangleWidth,6px);
border-style: solid;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: #ccc;
border-bottom-color: white;
}
.jf-select-list-ul{
width: 100%;
/* height: 100%; */
padding-left: 0;
box-sizing: border-box;
border: solid 1px var(--selectListBoderColor);
border-radius:var(--selectListRadius);
margin-top: var(--selectTriangleWidth);
margin-bottom: 0;
overflow-y:scroll;
}
.jf-select-list-ul>li{
list-style: none;
padding-left:var(--selectListPadding,var(--padding));
font-size:var(--selectListFontSize);
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
}
.jf-select-list-ul>li:hover{
background-color: #F5F7FA;
}
.jf-select-list-ul::-webkit-scrollbar {
width: 5px;
background-color: transparent;
}
.jf-select-list-ul::-webkit-scrollbar-thumb {
border-radius: 20px;
background-color: #D0D0D1;
}
.jf-select-list-ul::-webkit-scrollbar-track {
background-color: transparent;
border-radius: 5px;
}