我有一个包含大约2k项目的列表。如果我对每个孩子使用onClick,我最终会得到2k听众,这就是我目前所拥有的。我想做一些事情,比如让父组件听取点击事件。但是,如果我这样做,我就没有引用我需要调用setState的子组件。还可以动态过滤子组件列表(使用this.refs可能不好?)。
我能想到的最好的方法是将子组件id的哈希映射到父组件中的子组件,并在单击时查找视图。
仅用于说明目的:
var Parent = React.createClass({
shouldComponentUpdate: function() { return false; },
handler: function(e) {
// look up from reference and set state
},
componentWillUnmount: function() {
// clean up reference
},
render: function() {
this.reference = {};
var items = [];
for(var i = 0; i < this.props.items.length; i++) {
var child = React.createClass(Child, {id: this.props.items[i].id});
items.push(child);
reference[child.id] = child;
}
return React.createClass('div', {onClick: this.handler}, items);
}
})
我想知道是否有React处理这个问题的方法。
答案 0 :(得分:3)
我认为这个答案可能会有所帮助......如果您有2000个事件处理程序或只有一个事件处理程序并不重要。 React以同样的方式处理它。请记住,您在render方法中返回的HTML不会添加到DOM中,但它只是由React用于构建虚拟DOM表示。最后,React只有一个onClick。
React efficient way to bind event to many dom elements
如果你需要知道触发点击的元素,你只需要访问event.target并使用任何数据属性来识别被点击的元素。
答案 1 :(得分:1)
React的做法是使用Flux调度程序+商店。基本上,一旦商店执行了您希望它完成的任务,您就可以将每个项目绑定到从商店触发的事件。
所以流程将是:
项目被点击=&gt;调度Flux事件=&gt; Flux调度程序检测事件并使用从Item组件传递的数据执行适当的函数。
var ItemStore = {
doSomething: function(data){
// do something with the data
}
}
MicroEvent.mixin(ItemStore);
var AppDispatcher = new Dispatcher();
AppDispatcher.register(function(payload) {
switch (payload.eventName) {
case 'item-clicked':
ItemStore.doSomething(payload.data.someData);
ItemStore.trigger('did-something');
}
return true;
})
var Item = React.createClass({
shouldComponentUpdate: function() { return false; },
componentDidMount: function() {
ItemStore.bind('did-something', this.submitHandled);
},
handler: function(e) {
AppDispatcher.dispatch({
eventName: 'item-clicked',
data: {
someData: 'sample data'
}
});
},
componentWillUnmount: function() {
// clean up reference
},
submitHandled: function() {
// do something after the click
},
render: function() {
// insert your item's html here.
}
})
答案 2 :(得分:1)
以 @damianmr 的答案为基础,这里是an example。
var Child = React.createClass({
shouldComponentUpdate(nextProps){
if (this.props.text !== nextProps.text) return true;
if (this.props.active !== nextProps.active) return true;
return false;
},
render(){
var className = 'Child';
if (this.props.active) className += ' Child-active';
return (
<div {...this.props} className={className}>
{this.props.text}
</div>
);
}
});
var Parent = React.createClass({
getInitialState(){
return {active: -1};
},
setActive(id){
this.setState({active: id});
},
render(){
return (
<div>
{this.props.items.map((item) => {
return (
<Child
active={this.state.active === item.id}
onClick={() => this.setActive(item.id)}
text={'My id is ' + item.id}
key={item.id}
/>
);
})}
</div>
);
}
});