尝试使用React创建一个选中和取消选择其他单个复选框(选择/取消全选)的复选框时,我遇到了一些问题。我看过http://facebook.github.io/react/docs/forms.html并发现受控和不受控制 <input>
之间存在差异。我的测试代码如下:
var Test = React.createClass({
getInitialState: function() {
return {
data: [
{ id: 1, selected: false },
{ id: 2, selected: false },
{ id: 3, selected: false },
{ id: 4, selected: false }
]
};
},
render: function() {
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} />
{d.id}
<br />
</div>
);
});
return (
<form>
<input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector
<br />
{checks}
</form>
);
},
__changeSelection: function(e) {
var id = e.target.getAttribute('data-id');
var state = this.state.data.map(function(d) {
return {
id: d.id,
selected: (d.id === id ? !d.selected : d.selected)
};
});
this.setState({ data: state });
},
__changeAllChecks: function(e) {
var value = this.refs.globalSelector.getDOMNode().checked;
var state = this.state.data.map(function(d) {
return { id: d.id, selected: value };
});
this.setState({ data: state });
}
});
React.renderComponent(<Test />, document.getElementById('content'));
“全局选择器”按预期工作:选中后,将选中所有其他检查。问题是,当单击其他复选框之一时,不会触发__changeSelection()
处理程序。
我不知道做这项工作的正确方法是什么。也许React模型不是模拟这种交互的最佳模型?我该怎么办?
提前致谢
答案 0 :(得分:43)
在render
函数中,this
映射函数的checks
范围与render
不同,后者是__changeSelection
所需的范围,因此this.__changeSelection
无法找到__changeSelection
属性。如果您在该映射函数的末尾添加.bind(this)
,则可以将其范围绑定到与this
相同的render
:
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} />
{d.id}
<br />
</div>
);
}.bind(this));
在旁注中,我只是将id
传递给处理函数而不是分配数据属性。这将消除在处理程序中找到该元素的需要:
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} />
{d.id}
<br />
</div>
);
}.bind(this));
然后更新您的__changeSelection
函数以传递id
作为第一个arg并删除属性查找行:
__changeSelection: function(id) {
var state = this.state.data.map(function(d) {
return {
id: d.id,
selected: (d.id === id ? !d.selected : d.selected)
};
});
this.setState({ data: state });
}
这是一个放在一起的例子along with a jsfiddle for you to try it out:
/** @jsx React.DOM */
var Test = React.createClass({
getInitialState: function() {
return {
data: [
{ id: 1, selected: false },
{ id: 2, selected: false },
{ id: 3, selected: false },
{ id: 4, selected: false }
]
};
},
render: function() {
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} />
{d.id}
<br />
</div>
);
}.bind(this));
return (
<form>
<input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector
<br />
{checks}
</form>
);
},
__changeSelection: function(id) {
var state = this.state.data.map(function(d) {
return {
id: d.id,
selected: (d.id === id ? !d.selected : d.selected)
};
});
this.setState({ data: state });
},
__changeAllChecks: function() {
var value = this.refs.globalSelector.getDOMNode().checked;
var state = this.state.data.map(function(d) {
return { id: d.id, selected: value };
});
this.setState({ data: state });
}
});
React.renderComponent(<Test />, document.getElementById('content'));
答案 1 :(得分:3)
如果您正在处理复选框,则可以使用checkedLink
属性。这是另一种可能的实现,它使全局复选框受到控制(而不是在当前答案中不受控制):
var Test = React.createClass({
getInitialState: function() {
return {
globalCheckbox: false,
data: [
{ id: 1, selected: false },
{ id: 2, selected: false },
{ id: 3, selected: false },
{ id: 4, selected: false }
]
};
},
changeCheckForId: function(id,bool) {
this.setState(
{
data: this.state.data.map(function(d) {
var newSelected = (d.id === id ? bool : d.selected);
return {id: d.id, selected: newSelected};
}
)});
},
changeCheckForAll: function(bool) {
this.setState({
globalCheckbox: true,
data: this.state.data.map(function(d) {
return {id: d.id, selected: bool};
})
});
},
linkCheckbox: function(d) {
return {
value: d.selected,
requestChange: function(bool) { this.changeCheckForId(d.id,bool); }.bind(this)
};
},
linkGlobalCheckbox: function() {
return {
value: this.state.globalCheckbox,
requestChange: function(bool) { this.changeCheckForAll(bool); }.bind(this)
};
},
render: function() {
var checks = this.state.data.map(function(d) {
return (
<div>
<input key={d.id} type="checkbox" checkedLink={this.linkCheckbox(d)} />
{d.id}
<br />
</div>
);
}.bind(this));
return (
<form>
<input type="checkbox" checkedLink={this.linkGlobalCheckbox()} />Global selector
<br />
{checks}
</form>
);
},
});
如果要变异的状态没有深度嵌套,那么checkedLink=this.linkState("checkboxValue")
和LinkedStateMixin
一起使用会更简单(就像这个问题中的情况一样)
修改:checkedLink
和valueLink
已被弃用,但在之前的React版本中受到推荐。