下面是一个简单的demo:
版本一:
import React from 'react';
class GroupItem extends React.Component{
constructor(props) {
super(props);
this.state = {
groupListData : props.groupListData,
delGroup : props.delGroup,
editGroup : props.editGroup
};
this.del = this.del.bind(this);
}
del(id){
console.log(id);
console.log('删除分组');
}
render(){
return (
<ul className="lcx02_newGroup-list">
{this.state.groupListData.map((item) => {
return (<li><span className="text-ellP">{item.name}</span><span onClick={this.del(item.id)} className="lcx02_delete fr" /><span className="lcx02_edit fr" /></li>)
})}
</ul>
);
}
}
GroupItem.propTypes = {
groupListData : React.PropTypes.arrayOf(React.PropTypes.shape({})),
delGroup : React.PropTypes.func
};
export default GroupItem;
版本二:
const GroupItem = ({groupListData, delGroup, editGroup}) => {
return (
<ul className="lcx02_newGroup-list">
{groupListData.map((item) => {return (<li><span className="text-ellP">{item.name}</span><span onClick={delGroup(item.id)} className="lcx02_delete fr" /><span onClick={editGroup(item.id)} className="lcx02_edit fr" /></li>)})}
</ul>
);
};
GroupItem.propTypes = {
groupListData : React.PropTypes.arrayOf(React.PropTypes.shape({})),
delGroup : React.PropTypes.func,
editGroup : React.PropTypes.func
};
li里面的点击删除事件如何传递呢?是不是思路错了?求大神指教一下。
对事件的赋值的概念是”回调函数”的概念,不是”调用函数”,是给于如onClick方法一个”函数”作为值,而不是给于一个函数调用,除非这个函数调用后会回传另一个函数。
什么是”函数调用”,下面这个就是,除非有特别用意,这十之八九是错误的用法:
<ABC onClick={editGroup(item.id)} />
什么是赋于一个回调函数,下面这二个例子就是,这经常可见,通常会是正确用法:
<ABC onClick={editGroup} />
<ABC onClick={() => { editGroup(item.id) }} />
上面的第二种语法,它在React中会有执行期绑到里面的值的设计,类似于部份应用的概念,这是比较特别的。它可以用来当你在事件触发时有不同的传参时,要作一些其它的用途,例如像这里的要分辨是要删除哪个项目。
当你需要更多的传参时,也需要传入的事件对象时,就会写成像下面的语法:
<ABC onClick={(e) => { editGroup(item.id, e) }} />
而对应的触发事件时用的方法,应该也是同样的方法声明:
editGroup(id, e){
// 这里写代码
}
或使用相似于箭头函数语法,可以省去在构造式里面作bind,如下:
editGroup = (id, e) => {
// 这里写代码
}
以上为概略地对事件触发的赋给回调函数的说明。
那么,回头来看看题主的代码,这代码中有什么问题。
首先,在不论是版本一或版本二,对于onClick事件,都是赋给一个”函数的调用”,所以不论是
onClick={this.del(item.id)}
或
onClick={delGroup(item.id)}
,必定不是那种鼠标点了后,触发事件然后作某些事情的结果。这与上面说的内容相违背。应该是要改为上面说的第二种,多个传参的语法,这就不多说了。
另一种方式在事件处理也很常见,有些特定的情况,可能没法在渲染的时候就能得到这种
item.id
值,或是它还不是个真正对应到真实DOM元素的事件方法(例如先赋到某个自订元件上)。这时候就要用别的技巧来作,实际上这与使用jQuery或纯JS来处理DOM元素上的事件类似的技巧,只是场景换到React上来而已。
一个简单的例子像下面这样,这是在点了
li
元素后,会删除掉自己
li
元素的例子:
AppTest.js
import React from 'react'
import Item from './Item'
class AppTest extends React.Component {
constructor() {
super()
this.state = {
items: ['aaa', 'bar', 'cat', 'foo'],
}
}
handleItemClick = (e) => {
const items = this.state.items.filter((item, index) => (
index !== +e.target.getAttribute('id')
))
this.setState({
items,
})
}
render() {
return (
<ul>
{
this.state.items.map((item, index) => (
<Item
text={item}
key={index}
index={index}
onClick={this.handleItemClick}
/>
))
}
</ul>
)
}
}
export default AppTest
Item.js
import React from 'react'
const Item = (props) => (
<li
id={props.index}
onClick={props.onClick}
>
{props.text}
</li>
)
export default Item
关键是用了一个
xxx
在
li
元素上,这个值代表数组中的索引值,然后在事件触发时,可以用下面的语法来获取这个值(加一元正号是为了强制转为数字而已),
id
随便取的,你要取
index
也可以,只要前面是
就可以:
index !== +e.target.getAttribute('id')
也就是说这种方式,不需要在事件触发的回调函数,使用多个传参的语法。而是用
xxx
的对DOM元素的赋值,自行命名在真实DOM元素出现时的一些数据,这可以在某些情况下提供了一些便利。
*
属性还可以用下面的其它两种方式获取到值:
e.target.attributes.getNamedItem('id').value
e.target.dataset.id
onClick={this.del(item.id)}
onClick直接调用this.del时,item.id只会当成del函数的第二个参数,第一个参数是event对象。
你可以用下面两种方式:
1、 调用时只传item.id
render(){
return (
<ul className="lcx02_newGroup-list">
{this.state.groupListData.map((item) => {
return (<li>
<span className="text-ellP">{item.name}</span>
<span onClick={() => { this.del(item.id) } } className="lcx02_delete fr" />
<span className="lcx02_edit fr" />
</li>)
})}
</ul>
);
}
2. onClick不变,改变del函数取参数的方式
render(){
return (
<ul className="lcx02_newGroup-list">
{this.state.groupListData.map((item) => {
return (<li>
<span className="text-ellP">{item.name}</span>
<span onClick={ this.del.bind(this, item.id) } className="lcx02_delete fr" />
<span className="lcx02_edit fr" />
</li>)
})}
</ul>
);
}
del(event, id){
console.log(id);
console.log('删除分组');
}
你的这个意思是子组件调用父组件的方法吗??如果是,穿参数跟平时都一样的啊,例如
//父组件其中的一个方法
del(id){
//这个id=123,如下面的一样
}
render(
return(
<div>
<子组件 del={this.del} />
</div>
)
)
子组件在调用的时候就是这样了
//子组件内
click(id){
this.props.del(id) //假如这个id=123
}
{
..map( (item,index) => { return ( <li onClick={this.click(item.uuid)}>123</li>)})
}