如何写好一个react组件 2016-04-17 tech 正文 设置默认属性 defaultProps 属性检测 propTypes 构造函数:获取默认值,绑定函数 Controlled Componennt:更新Value 更新state,回调onChange 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153import React from 'react';import RaisedButton from 'material-ui/lib/raised-button';//定义内部样式const minBtnStyle = { height: '30px', margin: '5px 0', marginLeft: '10px', minWidth: 'auto'};const minBtnLabelStyle = { lineHeight: '30px'};class BSelect extends React.Component { //1、设置默认属性 static defaultProps = { /* 选择列表 */ checkList: [], /* 根元素类名 */ className: undefined, /* 默认值,multi为true时,是数组 */ defaultValue: undefined, /* 组件说明文字 */ label: undefined, /* 是否启用多选 */ multi: false, /* 选中的值,是否是Controlled Components */ value: undefined, /* event */ onChange: undefined } //2、属性检测 static propTypes = { checkList: React.PropTypes.array.isRequired, className: React.PropTypes.string, defaultValue: (props, propName) => { if(props.multi) { if(props[propName] && !(props[propName] instanceof Array)) { return new Error('defaultValue should be Array cause multi is true'); } } }, label: React.PropTypes.string, multi: React.PropTypes.bool, value: (props, propName) => { if(props.multi) { if(props[propName] && !(props[propName] instanceof Array)) { return new Error('value should be Array cause multi is true'); } } }, onChange: React.PropTypes.func } //3、构造函数:获取默认值,绑定函数 constructor(props) { super(props); this._updateState = this._updateState.bind(this); this._setValue = this._setValue.bind(this); this.isMulti = this.props.multi; //init states this.state = { value: this.props.defaultValue === undefined ? this.isMulti ? [] : '' : this.props.defaultValue }; } componentWillMount() {} //4、Controlled Componennt:更新Value componentWillReceiveProps(nextProps) { this._setValue(nextProps, nextProps.value); } _setValue(props, value) { if(value !== undefined) { if(this.isMulti) { this.state.value = value === undefined ? [] : value; } else { this.state.value = value === undefined ? '' : value; } } } //5、更新state,回调onChange _updateState() { if(typeof this.props.onChange === 'function') { this.props.onChange(this.state.value); } this.setState({ value: this.state.value }); } render() { let labelText = this.props.label; let labelElement = labelText ? <label>{labelText + ':'}</label> : ''; return ( <div className={'row pdl1 pdr1 middle-xs ' + (this.props.className || '')}> {labelElement} <div className='col-xs nopadding'> { this.props.checkList.map((v, i) => { return ( <RaisedButton className={v.btnClassName} disabled={v.disabled} label={v.label} labelStyle={minBtnLabelStyle} key={i} onClick={() => { if(this.isMulti) { let index = this.state.value.indexOf(v.value); if(index !== -1) { this.state.value.splice(index, 1); } else { this.state.value.push(v.value); } } else { this.state.value = v.value; } this._updateState(); }} secondary={(() => { if(this.state.value instanceof Array) { return this.state.value.includes(v.value); } else { return this.state.value === v.value; } })()} style={minBtnStyle}/> ) }) } </div> </div> ) }}export default BSelect; < react es6 装饰器 Material Icons can't display ? >