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

Posted

技术标签:

【中文标题】如何从 React 中的事件对象访问自定义属性?【英文标题】:How to access custom attributes from event object in React? 【发布时间】:2013-12-21 02:02:57 【问题描述】:

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

如果你想使用自定义属性,你应该在它前面加上 数据-。

<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"]

这些都不起作用。

【问题讨论】:

可能是一条评论对某人有帮助,我发现 React 16.7 doesnt rerenders 并更新组件的自定义 html 属性,如果您只更改了它们存储(fe redux)并绑定到组件。这意味着组件具有 fearia-modal=true,您将更改(为 false)推送到 aria/data 属性的存储区,但没有其他任何更改(例如组件的内容或类或变量) ) 结果 ReactJs 不会更新该组件中的 aria/data attrs。我一直在搞砸一整天才意识到这一点。 【参考方案1】:

我认为建议绑定所有需要使用 this.setState 方法的方法,该方法在 React.Component 类中定义,在构造函数中,在你的如果你的构造函数应该是这样的

    constructor() 
        super()
        //This binding removeTag is necessary to make `this` work in the callback
        this.removeTag = this.removeTag.bind(this)
    
    removeTag(event)
        console.log(event.target)
        //use Object destructuring to fetch all element values''
        const style, dataset = event.target
        console.log(style)
        console.log(dataset.tag)
    
   render() 
   ...
      <a data-tag=i style=showStyle onClick=this.removeTag.bind(null, i)></a>
   ...,

有关对象解构的更多参考 https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Operators/Destructuring_assignment#Object_destructuring

【讨论】:

【参考方案2】:

您可以简单地使用 event.target.dataset 对象。这将为您提供具有所有数据属性的对象。

【讨论】:

【参考方案3】:

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

您可以选择event.target.dataset.tagevent.target.getAttribute('data-tag');任何一个都可以。

【讨论】:

react 0.13.3,IE10 event.target.dataset 未定义,但 event.target.getAttribute('data-tag') 有效。其他浏览器都很好。谢谢 这种方法有什么问题吗?例如,根据用户按下的按钮,我想将字符串传递给函数。我希望避免在每种情况下在我的组件中创建三个函数。 这个答案在性能方面比公认的要好。这样做意味着我们在每次渲染时都创建一个新函数。它不仅跳过每次渲染创建一个新函数,而且由于每次函数引用都是相同的,纯(或记忆化)组件不会将其视为不同的函数。因此,它不会每次都不必要地重新渲染整个组件。即使是 shouldComponentUpdate 的自定义实现也会有同样的问题,除非你完全忽略了函数 prop。 我使用打字稿。就我而言,我不得不使用event.currentTarget.getAttibute('data-tag') 这个答案不正确,结果不可靠。请使用e.currentTarget.getAttribute()【参考方案4】:

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

event.currentTarget.getAttribute('data-tag')

【讨论】:

【参考方案5】:

你可以像这样访问数据属性

event.target.dataset.tag

【讨论】:

【参考方案6】:

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

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

【讨论】:

看起来很棒!我怎么能看到分配 dom 属性要慢得多【参考方案7】:
<div className='btn' onClick=(e) =>
     console.log(e.currentTarget.attributes['tag'].value)
     tag='bold'>
    <i className='fa fa-bold' />
</div>

所以e.currentTarget.attributes['tag'].value 为我工作

【讨论】:

【参考方案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); 

【讨论】:

“我”从何而来? i 是 OP 想要以某种方式传入的自定义属性。这是定义 a 元素时范围内的一些变量。 这不是 OP 想要的。他们想使用 onClick 处理程序访问元素 (a) 上的属性值。 我的意思是,官方的解决方案是在范围内定义带有变量的事件处理函数,而不是在元素上设置数据属性。如果你真的想要,这不会阻止你访问元素的属性,但这不是在 React 中访问变量的惯用方式。【参考方案9】:

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

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

看起来 React 这样做是为了让它可以在更多浏览器上运行。您可以通过 nativeEvent 属性访问旧属性。

【讨论】:

【参考方案10】:
// 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>

【讨论】:

在你的代码中添加一些描述,让其他人理解代码【参考方案11】:

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

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

【讨论】:

【参考方案12】:

为了帮助您以可能与您所要求的方式不同的方式获得所需的结果:

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=() =&gt; this.removeTag(i) 而不是 .bind

【讨论】:

但您不再获得通过的事件对象。 @chovy 如果我错了,请纠正我,但不是所有的 javascript 函数本质上都是可变的吗?我没有对此进行测试,但我认为“事件对象”仍在传递。它只是与以前不同的参数索引。以上述方式绑定就像unshifting 函数arguments 数组。如果“事件对象”位于索引 0,它现在将位于索引 1 @chovy 如果你需要,你可以。就做removeTag: function(i, evt) 它更简洁,但如果您执行大量绑定,所有这些绑定都会对性能造成影响。 github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/…【参考方案13】:

这是我找到的最好方法:

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

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

【讨论】:

您可能想添加.value 以获取实际值 我已经编辑了答案,按照@Wikunia 的建议在末尾添加了.value【参考方案14】:

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

1) 在 html-tag 中定义一个带有 data- 前缀的新属性

data-mydatafield = "asdasdasdaad"

2) 使用

从 javascript 中获取
e.target.attributes.getNamedItem("data-mydatafield").value 

【讨论】:

我的一直说空【参考方案15】:

或者你可以使用闭包:

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 

【讨论】:

谢谢,都铎王朝。尝试了您的解决方案,它甚至可以在没有绑定的情况下工作。我用它来切换 e.target 上的样式。 你怎么知道一个内部函数会包含事件参数?

以上是关于如何从 React 中的事件对象访问自定义属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TypeScript v2.x 中从自定义 React 组件公开“通用”事件

如何从自定义弹出菜单扩展中的选择事件中获取所选对象值?

react native 中的 branch.io 自定义事件未触发奖励规则

如何用Lua来访问Unity 控件的属性

React 组件中的事件处理组件(受控非受控)函数柯里化

为自定义控件实现值访问器时,未从事件中的模型获取更新值