组件化思路:以selection为例子,使用prop-types实现组件化控制,重用

需求

书接上文,UI 积累之select sectioncss

这里又来两个需求了。react

  • 当我点击选择了option后,我应该看到的是我选择的option的内容segmentfault

  • 多例重用,即一样是个selection,我只是须要改点东西,其余不变,好比selection里面的字内容,font-size, font-family, selection的width, height等。。。如何只开发一个组件就知足这个“无理要求”呢?dom

第一只老虎--显示option内容

咱们的dom是这样的:组件化

<Selectsection>
    <select>
        <option>Please select one option...</option>
        <option>...</option>
        <option>...</option>
    </select>
    <span>Please select one option...</span>
    <div></div>
</Selectsection>

具体实现,经过react的state却是能很简单实现。ui

给select绑定个onChange事件,触发onSelect方法,当选择select的option的时候,把选到的值传给真正显示的spanthis

问题来了:1)怎么拿。 2)怎么给spa

1)怎么拿:设计

点击的时候,经过event.target.value拿到选中的option的值

2)怎么给:code

在组件渲染的时候,constructor里的state定义一个值存放选中的值,叫showValue,当选择时,在onSelect方法里,拿到event.target.value后,set给这个值,同时dom中的span进行this.state.showValue值绑定。

Talk is cheap, show me the code

完整代码以下:

class Selection extends Component {
    constructor(props){
        super(props)
        this.state = {
            showValue: "Please select one option..."
        }
    }

    onSelect(e){
        this.setState({showValue: e.target.value});
    }
    render() {
        return (
            <Selectsection>
                <select onChange={this.onSelect.bind(this)}>
                <option>Please select one option...</option>
                <option>...</option>
                <option>...</option>
                </select>
                <span>{this.state.showValue}</span>
                <div></div>
            </Selectsection>
        );
    }
}

实例图:

clipboard.png
clipboard.png

第二只老虎--组件化

看上面的代码能够知道,引入这个selection的方式是这样的

render(
    <Selection />
)

可是你这个selection啊,我同一个页面要引入N个,其中一个高度要是40px,另外一个宽度要长点,500px,还有一个长宽都不用变,你给我变下这个selection的default的字啊,不叫Please select one option..., 叫什么Please kindly select one option...,还有一个,你给我保持原样不变哈,谢谢了。

WTF, 怎么作呢?

需求啊,莫得办法

为了开发方便,我本身设计,要是能组件化,几个属性在引入的时候能够选择性定义就行了,好比:

render(
    <div>
        <Selection />
        <Selection  width="500px" />
        <Selection  height="40px" />
        <Selection  wordings="Please kindly select one option..."/ />
    </div>
)

能这么实现就完美了。

怎么作呢,这就要引入一个包,叫prop-types了,定义属于这个组件的变量,而后将其运用到组件的每一个dom的css上。
接下来以上述为例子。

定义属于这个组件的类型:

Selection.propTypes = {
    height: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.string,
    ]),
    width: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.string,
    ]),
    words: PropTypes.string
}

Selection.defaultProps = {
    height: '30px',
    width: '300px',
    words: 'Please select one option...'
}

而后就是经过react的this.props引入啦

Talk is cheap, show me the code

index.js

class App extends Component {
  render() {
    return (
        <div>
          <Selection />
          <Selection height="40px" />
          <Selection width="500px" />
          <Selection words="Please kindly select one option..." />
        </div>
    );
  }
}

Selection.js

class Selection extends Component {
    constructor(props){
        super(props)
        this.state = {
            showValue: this.props.words
        }
    }

    onSelect(e){
        this.setState({showValue: e.target.value});
        console.log(e.target.value)
    }
    render() {
        const { width, height } = this.props

        const style = {
            width: width,
            height: height            
        }

        const suitableHeight = (parseInt(height.substring(0, height.length-2)) - 30) / 2 + 6;
        
        const spanStyle = {
            width: width,
            height: height,
            paddingTop:suitableHeight
        }

        const arrowStyle = {
            top:suitableHeight
        }

        return (
            <Selectsection style={style}>
                <select onChange={this.onSelect.bind(this)} value={this.state.showValue} style={style}>
                    <option>{this.props.words}</option>
                    <option>...</option>
                    <option>...</option>
                </select>
                <span style={spanStyle}>{this.state.showValue}</span>
                <div style={arrowStyle}></div>
            </Selectsection>
        );
    }
}

Selection.propTypes = {
    height: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.string,
    ]),
    width: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.string,
    ]),
    words: PropTypes.string
}

Selection.defaultProps = {
    height: '30px',
    width: '300px',
    words: 'Please select one option...'
}

效果图:

clipboard.png

hm。。。应该差很少了,这里代码里就忽略了

  • 自定义属性时候纯数字和字符串的判断

  • 当height是比30小的时候的判断处理

有兴趣本身加

ok,完美收工

相关文章
相关标签/搜索