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


213

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????}); 
},

元素和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"]

这些都不起作用。


1
可能是一个可以帮助某人的评论,我发现React 16.7 不会重新渲染并更新组件的自定义html属性,如果您仅在商店(fe redux)中更改了它们并将它们绑定到组件。这意味着该组件具有fe aria-modal=true,您将更改(为false)推送到aria / data属性存储,但没有其他更改(例如组件的内容或其中的类或变量),因为结果ReactJs不会更新aria / 该组件中的数据属性。我整天都在忙着意识到这一点。
AlexNikonov

Answers:


171

为了帮助您以与要求不同的方式获得期望的结果:

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

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

IMO这比依赖DOM事件干净得多。

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


17
但是您不再获得事件对象的传递。
chovy

9
@chovy如果我输入错了,请纠正我,但不是所有的javascript函数本身都是可变的吗?我尚未对此进行测试,但是我认为“事件对象”仍在传递中。它与以前的参数索引不同。如上所述的绑定方式类似于unshift函数参数数组。如果“事件对象”在索引处,0则现在将在index处1
莱德·布鲁克斯

8
@chovy如果需要的话可以。随便做吧removeTag: function(i, evt) {
Jared Forsyth'3

8
它更干净,但是如果您要进行很多绑定,那么所有这些绑定的确会对性能造成影响。
El Yobo


296

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

您可以执行以下任一操作;event.target.dataset.tag或者 event.target.getAttribute('data-tag')任一个。


24
反应0.13.3,IE10 event.target.dataset是未定义的,但event.target.getAttribute('data-tag')可以工作。其他浏览器都很好。谢谢
Andrey Borisko 2015年

这种方法有什么问题吗?例如,根据用户按下的按钮,我想将字符串传递给函数。我希望避免为每种情况在组件中创建三个函数。
Michael J. Calkins

4
就性能而言,这个答案比公认的要好。这样做意味着我们不会在每个渲染上都创建一个新函数。它不仅跳过每个渲染创建新函数的过程,而且由于函数引用每次都相同,因此纯(或记忆化)组件不会将其视为不同的函数。因此,它不会每次都不必要地重新渲染整个组件。shouldComponentUpdate除非您完全忽略了函数prop,否则即使是的自定义实现也会遇到相同的问题。
Michael Yaworski '19年

效果非常好
Ogbonna Vitalis,

1
我用打字稿。就我而言,我不得不使用event.currentTarget.getAttibute('data-tag')
karianpour

50

这是我发现的最好方法:

var attribute = event.target.attributes.getNamedItem('data-tag').value;

这些属性存储在“ NamedNodeMap”中,您可以使用getNamedItem方法轻松访问。


4
您可能想要添加一个.value以获取实际值
Wikunia

我已经.value按照@Wikunia的建议编辑了答案,并在末尾添加了
fguillen

25

或者您可以使用闭包:

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 
}

3
谢谢,都铎。尝试过您的解决方案,即使没有绑定也可以使用。我用它来切换e.target上的样式。
andriy_sof

您如何知道内部函数将包含事件args?
jack.the.ripper

20
// 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>

1
在您的代码中添加一些说明,以使其他人了解该代码
Aniruddha Das

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}); 
}

1
“ i”来自哪里?
Freshchris '19

2
i是OP希望通过的自定义属性。a定义元素时,它是范围内的某个变量。
tytk

这不是OP想要的。他们希望使用onClick处理程序访问元素(a)上的属性值。
由Adrian

1
我的观点是,官方解决方案是使用范围内的变量定义事件处理函数,而不是在元素上设置数据属性。如果确实需要,这不会阻止您访问元素的属性,但这不是在React中访问变量的惯用方式。
tytk




3

我不了解React,但是在一般情况下,您可以像这样传递自定义属性:

1)在html标签内定义一个带有data-前缀的新属性

data-mydatafield = "asdasdasdaad"

2)从javascript获取

e.target.attributes.getNamedItem("data-mydatafield").value 

我一直说空
-Si8

3

如果有人试图在React中使用event.target并找到一个空值,那是因为SyntheticEvent取代了event.target。SyntheticEvent现在包含“ currentTarget”,例如在event.currentTarget.getAttribute('data-username')中。

https://facebook.github.io/react/docs/events.html

看起来React做到了这一点,因此它可以在更多浏览器上使用。您可以通过nativeEvent属性访问旧属性。


3

尝试不分配dom属性(这很慢),而只是将您的值作为参数传递给实际创建处理程序的函数:

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag = (customAttribute) => (event) => {
    this.setState({inputVal: customAttribute});
}

看起来像一个很棒的评论!我如何看到分配dom属性的速度要慢得多
Ido Bleicher


0

在React中,您不需要html数据,使用一个函数返回另一个函数;这样,发送自定义参数非常简单,您可以访问自定义数据和事件。

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag: (i) => (event) => {
    this.setState({inputVal: i}); 
},
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.