写在前面的话
h5为我们提供了select标签, 如果只是为了基本需求, 使用原生的就好, 然而作为一个有追求的咸鱼, 如何能够忍受原生那丑陋的UI呢, 因此我决定自己定制一个下拉框.
注: 使用原生select, 可以使用appearance:none;清除默认的箭头样式复制代码
开始定制
本文的写作环境为react 16.3.2 , css方面使用了stylus预编译器, 请一一对照, 废话不多说, 直接上代码.
// Select.js//本示例使用了CSS3 @keyframes和animation , ie要到10才支持, 请注意兼容性import React, { Component } from 'react'import arrowImg from '../images/arrow.png' //本地资源的一张图片export default class Select extends Component { constructor(props){ super(props) this.state = { select: '', //选中的值 isOption: false, //是否展示下拉菜单 options: this.props.valueArr|| [] //下拉菜单中的数组 } // 绑定this this.selectShow = this.selectShow.bind(this) this.selectHiden = this.selectHiden.bind(this) this.selectValue = this.selectValue.bind(this)} //显示下拉菜单 selectShow(){ this.setState({ isOption: true }) } //隐藏下拉菜单 selectHiden(){ this.setState({ isOption: false }) } //选择option selectValue(e){ let { id } = e.currentTarget.dataset let { options } = this.state this.setState({ select: options[id], isOption: false }, this.props.cb&&this.props.cb(options[id])) // cb为父级传入的函数, 简单示例 //
//select.styl .select-container width 200px display inline-block text-align center.select-value border-radius 5px border 1px solid rgba(0,0,0,0.3) position relative line-height 1 padding 5px 0 .select-value:hover border 1px solid #40a9ff .select-value-select border-radius 5px border 1px solid #40a9ff position relative line-height 1 padding 5px 0 .select-arrow position absolute right 10px width 20px height 20px animation rotateArrow 1s animation-fill-mode forwards.select-arrow-show position absolute right 10px width 20px height 20px animation rotateArrowShow 1s animation-fill-mode forwards@keyframes rotateArrow { from { transform:rotate(0deg); } to { transform: rotate(180deg) }}@keyframes rotateArrowShow{ from { transform: rotate(180deg) } to { transform: rotate(0deg) }}.select-moadl position absolute top 0 left 0 right 0 bottom 0 z-index 10 // background red .select-option-position position relative .select-option-container position absolute z-index 11 background rgba(0,0,0,0.15) width 200px .select-option:hover background #40a9ff color white .select-none display none复制代码
项目使用
import React from 'react'import Select from './Select'let valueArr = [2017,2018,2019]const App = () => (
这样, 自作版的下拉框就实现了, 样式如下图
关于下拉框的补充说明
因为本组件使用了自有生命周期来管理内部状态, 因此当你在项目中传入的valueArr在渲染之前就已经有值, 那么一切好说, 但是在正常使用过程中, valueArr 很可能还没有值, 就已经开始渲染了, 导致之后有值, 但是传进去也无效了, 因此需要告诉它, 记得更新数据, 加入react的生命周期
//react 16.3statice getDerivedStateFromProps(nextProps, preProps){ if(nextProps.valueArr.length){ return { options: nextProps.valueArr } } else return nextProps}//react 16.3 之前的componentWillReceiveProps(nextProps){ if(nextProps.valueArr.length){ this.setState({options: nextProps.valueArr } ) }}复制代码
这样就能解决异步传输问题了