如何从React中的事件对象访问自定义属性?

and*_*sof 183 javascript facebook reactjs

React能够呈现自定义属性,如 http://facebook.github.io/react/docs/jsx-gotchas.html中所述:

如果要使用自定义属性,则应在其前面加上data-.

<div data-custom-attribute="foo" />

这是个好消息,除了我找不到从事件对象访问它的方法,例如:

render: function() {
...
<a data-tag={i} style={showStyle} onClick={this.removeTag}></a>
...
removeTag: function(event) {
    this.setState({inputVal: event.target????}); 
},
Run Code Online (Sandbox Code Playgroud)

元素和data-属性在html中渲染很好.像标准属性一样style可以访问event.target.style.而不是event.target我试过:

 event.target.props.data.tag
 event.target.props.data["tag"]
 event.target.props["data-tag"]  
 event.target.data.tag
 event.target.data["tag"]
 event.target["data-tag"]
Run Code Online (Sandbox Code Playgroud)

这些都没有奏效.

Sop*_*ert 253

event.target为您提供本机DOM节点,然后您需要使用常规DOM API来访问属性.以下是有关如何执行此操作的文档:

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes#JavaScript_Access

你可以做任何一个event.target.dataset.tagevent.target.getAttribute('data-tag'); 两者都有效.

  • 反应0.13.3,IE10`event.target.dataset`未定义,但`event.target.getAttribute('data-tag')`有效.其他浏览器都很好.谢谢 (21认同)
  • 我使用打字稿。就我而言,我必须使用`event.currentTarget.getAttibute('data-tag')` (6认同)
  • 就性能而言,这个答案比公认的要好。这样做意味着我们*不*在每个渲染器上创建一个新函数。它不仅跳过每个渲染创建新函数的过程,而且由于函数引用每次都相同,因此纯(或记忆化)组件不会将其视为不同的函数。因此,它不会每次都不必要地重新渲染整个组件。甚至自定义实现“ shouldComponentUpdate”也将遇到相同的问题,除非您完全忽略了函数prop。 (2认同)
  • 这个答案是错误的,结果也不可靠。请使用`e.currentTarget.getAttribute()` (2认同)

Jar*_*yth 159

为了帮助您以与您提出的不同的方式获得理想的结果:

render: function() {
    ...
    <a data-tag={i} style={showStyle} onClick={this.removeTag.bind(null, i)}></a>
    ...
},
removeTag: function(i) {
    // do whatever
},
Run Code Online (Sandbox Code Playgroud)

请注意bind().因为这是所有javascript,你可以做这样的方便的事情.我们不再需要将数据附加到DOM节点以便跟踪它们.

IMO比依赖DOM事件要干净得多.

2017年4月更新:这些天我会写onClick={() => this.removeTag(i)}而不是.bind

  • 但是你不再获得传递的事件对象. (16认同)
  • @chovy请纠正我,如果我错了,但不是所有的javascript函数固有的变量?我没有测试过这个,但我认为"事件对象"仍在传递中.它与之前的参数索引不同.以上面概述的方式绑定就像`unshift`函数[arguments](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)数组.如果"事件对象"在索引"0"处,它现在将处于索引"1". (9认同)
  • @chovy你可以,如果你需要它.做`removeTag:function(i,evt){` (8认同)
  • 它更干净,但是如果你做了很多这样的绑定,所有这些绑定确实都会受到影响. (6认同)
  • https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md (6认同)
  • @JaredForsyth并不是.bind本身会影响你的表现,而是每个渲染分配一个新函数会破坏浅层相等.因此,如果您在[shallowCompare](https://facebook.github.io/react/docs/shallow-compare.html)中使用任何`shouldComponentUpdate`,则可以保证每次渲染都返回false.我认为React可以利用浅平等进行优化. (4认同)
  • 每当新函数和DOM更新时,bind()都会返回。这不是一种反应方式。 (2认同)

roc*_*imo 47

这是我发现的最佳方式:

var attribute = event.target.attributes.getNamedItem('data-tag').value;
Run Code Online (Sandbox Code Playgroud)

这些属性存储在"NamedNodeMap"中,您可以使用getNamedItem方法轻松访问它们.

  • 您可能想要添加一个`.value`来获取实际值 (4认同)

小智 24

或者你可以使用一个闭包:

render: function() {
...
<a data-tag={i} style={showStyle} onClick={this.removeTag(i)}></a>
...
},
removeTag: function (i) {
    return function (e) {
    // and you get both `i` and the event `e`
    }.bind(this) //important to bind function 
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,都铎王朝.尝试了你的解决方案,甚至没有绑定.我用它在e.target上切换样式. (3认同)

小智 18

// Method inside the component
userClick(event){
 let tag = event.currentTarget.dataset.tag;
 console.log(tag); // should return Tagvalue
}
// when render element
<a data-tag="TagValue" onClick={this.userClick}>Click me</a>
Run Code Online (Sandbox Code Playgroud)

  • 在你的代码中添加一些描述,让其他人理解代码 (2认同)

tyt*_*ytk 8

从React v16.1.1(2017)开始,这是官方解决方案:https://reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers

TLDR: OP应该做:

render: function() {
...
<a style={showStyle} onClick={(e) => this.removeTag(i, e)}></a>
...
removeTag: function(i, event) {
    this.setState({inputVal: i}); 
}
Run Code Online (Sandbox Code Playgroud)

  • “ i”是OP希望以某种方式传递的自定义属性。定义`a`元素时,这是一个范围内的变量。 (2认同)

Man*_*tam 8

<div className='btn' onClick={(e) =>
     console.log(e.currentTarget.attributes['tag'].value)}
     tag='bold'>
    <i className='fa fa-bold' />
</div>
Run Code Online (Sandbox Code Playgroud)

所以e.currentTarget.attributes['tag'].value对我有用


Eme*_*ine 7

这行代码为我解决了这个问题:

event.currentTarget.getAttribute('data-tag')
Run Code Online (Sandbox Code Playgroud)


Ram*_*bal 6

您可以访问这样的数据属性

event.target.dataset.tag
Run Code Online (Sandbox Code Playgroud)