我有一个选项列表,其中包含复选框和父ListView
内的完成按钮。按下完成按钮后,我想知道选中了哪个复选框。
我应该补充一点,我已尝试使用ListView
中的回调函数维护ChildCheckBox
中的复选框数组。它工作正常,除了导航回ListView
时,阵列将被重置,同时复选框似乎仍然被检查。我希望让onDonePress()
函数只查询检查哪些框然后在那时做出相应的响应,而不是依赖于ListView
维护一个数组。
以下是ListView
:
class ParentListView extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
};
}
componentDidMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(ROW_DATA),
});
}
onCheckPress() {
console.log('Check Pressed')
// callback from ChildCheckBoxCell...?
}
onDonePress() {
console.log('Done pressed')
// callback from ChildDoneCell...?
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
style={styles.listView}
/>
);
}
renderRow(cell) {
if (cell.type === 'ChildCheckBoxCell') {
return (
<ChildCheckBoxCell onChange={() => this.onCheckPress()} />
);
}
if (cell.type === 'ChildDoneCell') {
return (
<ChildDoneCell onDonePress={() => this.onDonePress()}/>
);
}
}
}
这是ChildCheckBoxCell
组件:
class ChildCheckBoxCell extends Component {
constructor(props) {
super(props);
this.state = {
isChecked: false,
};
}
onChange() {
this.setState({isChecked: !this.state.isChecked});
//Callback...
this.props.onChange();
}
render() {
return (
<TouchableHighlight onPress={() => this.onChange()}>
<Text>{this.state.isChecked? 'Checked' : 'UnChecked'}</Text>
</TouchableHighlight>
);
}
}
最后,这是ChildDoneCell
组件
class ChildDoneCell extends Component {
onDonePress() {
//Callback...
this.props.onDonePress();
}
render() {
return (
<TouchableHighlight onPress={() => this.onDonePress()}>
<Text>DONE</Text>
</TouchableHighlight>
);
}
}
提前致谢!
答案 0 :(得分:4)
这是你应该做的。我在代码中包含了注释来解释。应该有6个步骤。
class ParentListView extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
};
}
componentDidMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(ROW_DATA),
});
}
// 1. Change your callback functions to class properties
// this way it is auto-bound to this class instance and you don't bind it during render, which
// creates rendering overhead. Notice how the selected `cell` is
// passed in here. It will be explained in the last steps how that happens.
onCheckPress = (cell) => {
// Update the `isChecked` state of this cell and update
// your `ListView.DataSource` with it
console.log('Check Pressed', cell);
// callback from ChildCheckBoxCell...?
};
// 2. Do the same thing here as step 1.
onDonePress = (cell) => {
console.log('Done pressed', cell);
// callback from ChildDoneCell...?
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
style={styles.listView}
/>
);
}
renderRow(cell) {
if (cell.type === 'ChildCheckBoxCell') {
return (
// 3. You should pass in the cell data down here AND you should
// pass a reference to your callback
<ChildCheckBoxCell cell={cell} onChange={this.onCheckPress} />
);
}
if (cell.type === 'ChildDoneCell') {
// 4. Do the same thing here, except change the reference of
// the callback to the other callback, obviously
return (
<ChildDoneCell cell={cell} onDonePress={this.onDonePress}/>
);
}
}
}
class ChildCheckBoxCell extends Component {
render() {
return (
// 5. Dereference the function `onChange` and bind it to your
// `cell` object, don't worry about `null` changing your
// `this` context, it won't. This is how the `cell` object is
// passed an argument in the method on step 1.
<TouchableHighlight onPress={this.props.onChange.bind(null, this.props.cell)}>
{/* Stop using `state` to keep track of `isChecked`, you'll
lose this state if this ever is torn down and re-rendered
from the parent component */}
<Text>{this.props.cell.isChecked? 'Checked' : 'UnChecked'}</Text>
</TouchableHighlight>
);
}
}
class ChildDoneCell extends Component {
render() {
return (
// 6. This is the same thing as step 5.
<TouchableHighlight onPress={this.props.onDonePress.bind(null, this.props.cell)}>
<Text>DONE</Text>
</TouchableHighlight>
);
}
}
您会注意到您可以绑定cell
函数中的renderRow
数据,但不是首选。遵循的经验法则是,出于性能原因,您希望尽可能远地将您的回调函数取消引用到您的子数据,并且因为出于维护原因而更明确。这是替代方案:
// ParentListView
renderRow(cell) {
if (cell.type === 'ChildCheckBoxCell') {
return (
// No more passing of cell, but now I'm binding it with the
// cell object
<ChildCheckBoxCell onChange={this.props.onCheckPress.bind(null, cell)} />
);
}
if (cell.type === 'ChildDoneCell') {
// Same thing
return (
<ChildDoneCell onDonePress={this.onDonePress.bind(null, cell)}/>
);
}
}
// ChildCheckBoxCell
render() {
return (
// Notice how you lose the explicitness of your callback
// function and have no idea that this function implicitly passes
// the `cell` object because you prematurely bound it with the `cell` object
<TouchableHighlight onPress={this.props.onChange}>
<Text>{this.props.isChecked? 'Checked' : 'UnChecked'}</Text>
</TouchableHighlight>
);
}
修改强>
我更新了代码以使其更有意义并摆脱不必要的实例方法。我强烈建议您删除state
中的ChildCheckBoxCell
,并尝试通过props
将其作为cell
对象的一部分,在我的第一个示例中。< / p>