React 组件封装之 Select 选择框

一、Select 选择框

组件说明:
选择选项时出现弹框选择。

效果展示:
点击选项时出现下拉选择弹框。
实心铺满宽度为100%的效果![在这里插入图片描述](https://img-blog.csdnimg.cn/20190921185602283.png)

二、使用案例

import {Select} from 'share';
import React from 'react';
export default class Example extends React.Component {
    constructor(props) {
        super(props);
    }
    render(){
      return <Select
                options={this.state.typeList}
                babel="分类"
                onChange={this.changeType.bind(this)}
              />
    }
}

三、API 使用指南

属性说明类型默认值
options选项数组Array[]
babel选项标题string
onChange选中某一行的点击事件void

四、源代码

index.js

import React from 'react';
import right from '../images/select/right.png';
import select from '../images/select/select.png';
import './index.css';
import close from '../images/select/close.png';
import {defaultProps} from './defaultProps';
export default class Select extends React.Component {
    static defaultProps = defaultProps;
    constructor(props) {
        super(props);
        this.state = {
            isShow: false,
            active:(props.activeOne && props.activeOne.type-1)||0,
            value:'',
            id:'',
            bottomHeight:250,
        }
    }
    componentWillReceiveProps({options,onChange}){
        const isContainedInNumbers = options.some(number => number.id === this.state.id);
        if (isContainedInNumbers) {
            return;
        }
        this.state.value = this.props.activeOne && this.props.activeOne.name||options[0].name;//默认显示第一个类别
        this.state.id = this.props.activeOne && this.props.activeOne.type||options[0].id;//默认显示第一个类别id
        // 由于更新父组件state,导致父组件重新render,
        // 而React在render时,不管子组件属性是否改变,都会调用componentWillReceiveProps,
        // 因此会导致componentWillReceiveProps死循环
        // 不过没关系,前面加上了终止条件
        onChange(options[0]);
    }
    showBox(str) {
        this.setState({
            isShow: !this.state.isShow
        },()=>{
            if(str == "setHeight"){
                this.setHeight(this)
            }
        })
    }
    setHeight(that){
        var height = this.refs && this.refs.box.offsetHeight;
        if(height>=this.state.bottomHeight){
            console.log(that.refs.box);
            that.refs.box.style.height = this.state.bottomHeight+"px";
            that.refs.box.style.overflow = "scroll";
        }
    }
    closeBox(){
        this.setState({
            isShow: false
        })
    }
    change(item,index){
        const {onChange}=this.props;
        onChange(item);
        this.setState({
            value:item.name,
            active:index
        })
    }
    render() {
        const {prefixCls,options, babel} =this.props;
        return (
            <div className={prefixCls}>
                <div>{babel}</div>
                <div className={prefixCls+'-wrap'} onClick={() => this.showBox("setHeight")}>
                    <div>{this.state.value}</div>
                    <img src={right} alt="" className={prefixCls+'-arrow'}/>
                </div>
                {this.state.isShow ?
                    <div className={prefixCls+'-modal'}>
                        <div className={prefixCls+'-content'} ref="box" onClick={()=>this.showBox()}>
                            <div className={prefixCls+'-height'}>
                        <div className={prefixCls+'-item'}>
                            <div className={prefixCls+'-item-left'}>
                                <img className={prefixCls+'-item-icon'} src={select} alt="" onClick={()=>this.closeBox()}/>
                                <span className="cm-ml-10 cm-c-main">请选择分类</span>
                            </div>
                            <img  className={prefixCls+'-item-icon'} src={close} alt="" onClick={()=>this.closeBox()}/></div>
                            </div>
                        {options.map((item,index) => {
                            console.log(item);
                            return <div key={index} className={this.state.active == index? prefixCls+'-label-active':prefixCls+'-label'} onClick={()=>this.change(item,index)}>{item.name}</div>
                        })}
                        </div></div> : null}
            </div>
        )
    }
}

index.less

@import '../default';
@prefixCls: s-select;

/* 默认搜索bar */
.@{prefixCls} {
   display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  .@{prefixCls}-wrap{
      display: flex;
      align-items: center;
      .@{prefixCls}-arrow{
        width:@size-20
      }
    }
  .@{prefixCls}-modal{
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 9999;
    text-align: center;
    background: rgba(50,50,50,0.5);
    .@{prefixCls}-content{
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 9999;
      text-align: center;
      background: #ffffff;
      .@{prefixCls}-height{
        height: @size-40;
      .@{prefixCls}-item{
        color: @c-main;
        display: flex;
        align-items: center;
        justify-content: space-between;
        position: fixed;
        left: 0;
        right: 0;
        background: #ffffff;
        height: @size-40;
        line-height: @size-40;
        .@{prefixCls}-item-left{
          display: flex;
          align-items: center;
          margin-left: @size-10;
        }
      }
        .@{prefixCls}-item-icon{
          width: @size-20;
          margin-right: @size-10;
        }
      }
      .@{prefixCls}-label{
        height: @size-40;
        line-height: @size-40;
        color: @c-999;
        border-top:1px solid @border-c-base;
      }
      .@{prefixCls}-label-active{
        height: @size-40;
        line-height: @size-40;
        color: @c-main;
        border-top:1px solid @border-c-base;
      }
    }
  }
}

defaultProps.js

function noop() {}
export const defaultProps = {
    prefixCls: 's-select',
    options:[],
    babel:"",
    onChange:noop
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值