UNPKG

3.91 kBJavaScriptView Raw
1import React from 'react';
2import classnames from 'classnames';
3import PropTypes from 'prop-types';
4
5
6const propTypes = {
7 name: PropTypes.string,
8 /**
9 * 默认选中的值
10 */
11 defaultValue: PropTypes.oneOfType([
12 PropTypes.string,
13 PropTypes.number,
14 PropTypes.bool,
15 ]),
16 /**
17 * 选中的值
18 */
19 selectedValue: PropTypes.oneOfType([
20 PropTypes.string,
21 PropTypes.number,
22 PropTypes.bool,
23 ]),
24 /**
25 * 选中的值,作用与selectedValue一致,添加value属性是为了配合form表单校验初始化等一起使用
26 */
27 value: PropTypes.oneOfType([
28 PropTypes.string,
29 PropTypes.number,
30 PropTypes.bool,
31 ]),
32 /**
33 * 暴露给用户,且与子Radio通信的方法
34 */
35 onChange: PropTypes.func,
36 /**
37 * radio 大小
38 */
39 size: PropTypes.oneOf(['lg','sm']),
40
41 children: PropTypes.node.isRequired,
42
43 Component: PropTypes.oneOfType([
44 PropTypes.string,
45 PropTypes.func,
46 PropTypes.object
47 ]),
48 disabled: PropTypes.bool
49};
50
51const defaultProps = {
52 Component: 'div',
53 clsPrefix: 'u-radio-group',
54 defaultValue: ''
55};
56
57/**
58 * 与子Radio通信
59 */
60const childContextTypes = {
61 radioGroup: PropTypes.object
62}
63
64class RadioGroup extends React.Component {
65
66 constructor(props, context) {
67 super(props, context);
68 let initValue = 'value' in props ? props.value : ( 'selectedValue' in props ? props.selectedValue : props.defaultValue);
69 this.state={
70 focusvalue:'',
71 selectedValue: initValue
72 }
73 }
74
75 getValues = ()=>{
76 let array = []
77 let children = this.props.children;
78 if(!children){
79 console.error('RadioGroup must have child nodes');
80 return array;
81 }
82 if(children.length>1){
83 children.map((item)=>{
84 array.push(item.props.value)
85 })
86 }else if(children.length === 1){
87 array.push(children[0].props.value)
88 }else{
89 array.push(children.props.value);
90 }
91 return array;
92 }
93 componentDidMount(){
94 let array = this.getValues();
95 if(array.indexOf(this.props.selectedValue)==-1){
96 this.setState({
97 focusvalue:array[0]
98 })
99 }
100 }
101
102 componentWillReceiveProps(nextProps){
103 let array = this.getValues();
104 if(array.indexOf(this.props.selectedValue)==-1 || array.indexOf(this.props.value)==-1){
105 this.setState({
106 focusvalue:array[0]
107 })
108 }else{
109 this.setState({
110 focusvalue:''
111 })
112 }
113 if('selectedValue' in nextProps || 'value' in nextProps) {
114 this.setState({
115 selectedValue: nextProps.selectedValue !== undefined ? nextProps.selectedValue : nextProps.value
116 })
117 }
118 }
119
120 handleChange = (value) => {
121 let { onChange } = this.props;
122 if(!('selectedValue' in this.props)){
123 this.setState({
124 selectedValue: value
125 })
126 }
127 onChange && onChange(value);
128 }
129
130 /**
131 * 一旦外层change方法触发本身props发生改变,则调用getChildContext更新与子Radio的通信信息(radioGroup)
132 */
133
134 getChildContext() {
135 const {name, size} = this.props;
136 let { selectedValue } = this.state;
137 let onChange = this.handleChange;
138 return {
139 radioGroup: {
140 name, selectedValue, onChange,size,focusvalue:this.state.focusvalue
141 }
142 }
143 }
144
145 render () {
146 const {Component, name, selectedValue, onChange, children,size, clsPrefix, className, focusvalue, disabled, ...others} = this.props;
147
148 return (
149 <Component className={classnames(clsPrefix,className)} {...others} focusvalue={this.state.focusvalue}>
150 {
151 React.Children.map(children,child=>React.cloneElement(child,
152 {
153 disabled: child.props.disabled || disabled
154 }
155 ))
156 }
157 </Component>
158 );
159 }
160}
161
162RadioGroup.childContextTypes = childContextTypes;
163RadioGroup.propTypes = propTypes;
164RadioGroup.defaultProps = defaultProps;
165export default RadioGroup;
\No newline at end of file