組件化思路:以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,完美收工

相關文章
相關標籤/搜索