使用Reactjs,我希望有一个handleChange方法来处理所有表单元素的修改。
我理解LinkedStateMixin因此而存在,我应该使用
render: function() {
return <select multiple={{ true }} valueLink={this.linkState('value')}>...options...</select>;
}
绑定我的select元素的状态。
但似乎这种做事方式不适用于多个选择:state.value已更新但只有一个值(当我选择2个选项时,我可以看到React更新DOM并且它系统地删除了一个选择)。
所以我的问题是:LinkedStateMixin是这个用例的死胡同吗?你如何处理这个选择多用例?
答案 0 :(得分:3)
根本问题是具有.value
属性的select元素的multiple
仅返回它包含的第一个选定选项元素的值。因此,当ValueLink mixin调用event.target.value
来获取select
的新值时,它不会返回所需的数组以使value
属性生效。< / p>
您可以围绕select
构建一个小包装器以使其工作;这是我的版本(plus a JSFiddle example):
// A select element that supports `multiple` and `valueLink` correctly
var BetterSelect = React.createClass({
render: function() {
if (this.props.valueLink) {
return this.transferPropsTo(
<select value={this.props.valueLink.value}
valueLink={null} onChange={this.handleChange}>
{this.props.children}
</select>
);
} else {
return this.transferPropsTo(
<select onChange={this.handleChange}>
{this.props.children}
</select>
);
}
},
handleChange: function(e) {
var selectedValue;
if (this.props.multiple) {
// We have to iterate the `options` elements
// to figure out which ones are selected.
selectedValue = [];
var options = e.target.options;
for (var i = 0, l = options.length; i < l; i++) {
if (options[i].selected) {
selectedValue.push(options[i].value);
}
}
} else {
selectedValue = e.target.value;
}
// Fire onChange manually if it exists since we overwrote it
this.props.onChange && this.props.onChange(e);
// Finally, manually take care of any valueLink passed
if (this.props.valueLink) {
this.props.valueLink.requestChange(selectedValue);
}
}
});
// Let's try it out:
var Application = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return { value: ['Apples', 'Oranges'] };
},
render: function() {
return (
<div>
<pre>{JSON.stringify(this.state.value)}</pre>
<BetterSelect multiple valueLink={this.linkState('value')}>
<option value='Apples'>Apples</option>
<option value='Bananas'>Bananas</option>
<option value='Oranges'>Oranges</option>
</BetterSelect>
</div>
);
}
});