首页>demo13

Demo13 - 组件复合 by zuojj at 04 Jul 2016

本实例通过模拟多选select来实现组件的复合及父、子组件的交互。

HTML

<div id="container"></div>

CSS

.rc-select {
    width: 200px;
    margin: 10px auto;
    border: 1px solid #ccc;
    line-height: 36px;
}
.rc-select-header {
    border-bottom: 1px solid #ccc;
    padding: 5px;
    line-height: 20px;
    background-color: #fbfbfb;
    word-break: break-all;
}
.rc-select-body {
    padding: 5px; 
}
.rc-select-item {
    display: block;
    cursor: pointer;
}
.rc-select-item:not(:last-child) {
    border-bottom: 1px dashed #ccc;
}
.rc-select-checkbox {
    padding: 0;
    margin: 0 5px 0 0;
    vertical-align: -2px;
}

JAVASCRIPT

/**
 + 单个选项
 */
var MultipleSelectItem = React.createClass({
    propTypes: {
        text: React.PropTypes.string.isRequired,
        value: React.PropTypes.string.isRequired,
        checked: React.PropTypes.bool
    },
    getDefaultProps: function() {
        return {
            id: null,
            checked: false
        }
    },
    getInitialState: function() {
        return {
            checked: !! this.props.checked
        }
    },
    handleChange: function(e) {
        var obj = {
            checked: !this.state.checked
        };

        this.setState(obj);

        obj.index = this.props.index;

        this.props.handleClick(obj);
    },
    render: function() {
        return (
            <label className="rc-select-item" htmlFor={this.props.id}>
                <input type="checkbox" 
                    id={this.props.id}
                    value={this.props.value} 
                    checked={this.state.checked} 
                    className="rc-select-checkbox" 
                    onChange={this.handleChange} />
                <span className="rc-select-content">
                    {this.props.text}
                </span>
            </label>
        );
    }
});

// 父组件
var MultipleSelect = React.createClass({
    propTypes: {
        name: React.PropTypes.string.isRequired,
        placeholder: React.PropTypes.string.isRequired,
        data: React.PropTypes.array.isRequired
    },
    getInitialState: function() {
        return this.selected();
    },
    handleClick: function(obj) {
        this.props.data[obj.index].checked = obj.checked;

        this.setState(this.selected());
    },
    getItems: function() {
        var name = this.props.name;

        return this.props.data.map(function(item, index) {
            return <MultipleSelectItem 
                    key={index}
                    index={index}
                    id={name + '-' + index}
                    text={item.text} 
                    value={item.value} 
                    checked={!!item.checked}
                    handleClick={this.handleClick} />
        }.bind(this));
    },
    /**
     + [selected 处理选中]
     + @return {[type]} [description]
     */
    selected: function() {
        var values = [],
            texts  = [];

        this.props.data.map(function(item, index) {
            if(item.checked) {
                values.push(item.value);
                texts.push(item.text);    
            } 
        });

        return {
            values: values.length ? values.join(',') : '',
            texts: texts.length ? texts.join(',') : this.props.placeholder
        }
    },
    render: function() {
        return (
            <div className="rc-select">
                <input type="hidden" name={this.props.name} value={this.state.values} />
                <div className="rc-select-header">{this.state.texts}</div>
                <div className="rc-select-body">
                    {this.getItems()}
                </div>
            </div>
        );
    }
});


/**
 + 组件调用
 + @type {String}
 */
ReactDOM.render(
    <MultipleSelect 
    name="sex"
    placeholder="请选择省份" 
    data={
        [{
            value: '1',
            text: '北京'
        },{
            value: '2',
            text: '上海',
            checked: true
        },{
            value: '3',
            text: '重庆'
        },{
            value: '4',
            text: '天津'
        },{
            value: '5',
            text: '安徽'
        }]
    } />, document.getElementById('container'));