Як отримати доступ до спеціальних атрибутів з об’єкта події в React?


214

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

жоден із них не працював.


1
Можливо, один коментар допоможе комусь, я дізнався, що React 16.7 не ретранслюється та не оновлює користувацькі атрибути html компонента, якщо ви змінили їх лише у магазині (fe redux) та прив'язали до компонента. Це означає, що компонент має fe aria-modal=true, ви натискаєте зміни (на хибні) до складу атрибутів aria / data , але нічого іншого не змінюється (наприклад, вміст компонента чи клас чи змінні там), оскільки результат ReactJs не оновить aria / дані в цих компонентах. Я цілий день возився, щоб зрозуміти це.
AlexNikonov

Відповіді:


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: Ці дні я б писав onClick={() => this.removeTag(i)}замість.bind


17
але ви більше не передаєте об'єкт події.
човен

9
@chovy Будь-ласка, виправте мене, якщо я помиляюся, але чи не всі функції JavaScript по суті є різними? Я цього не перевіряв, але припускаю, що "об'єкт події" все ще передається. Це просто НЕ за тим самим індексом параметра, який був раніше. Пов'язане в моді, як описано вище, - це як масив аргументівunshift функції . Якщо "об'єкт події" був в індексі, він би зараз був в індексі . 01
Райдер Брукс

8
@chovy Ви можете, якщо вам це потрібно. Просто зробітьremoveTag: function(i, evt) {
Джаред Форсайт

8
Це чистіше, але всі ці прив'язки дійсно вдаряють, якщо ви робите багато з них.
El Yobo


297

event.targetдає вам власний вузол DOM, тоді вам потрібно використовувати звичайні API DOM для доступу до атрибутів. Ось документи, як це зробити: Використання атрибутів даних .

Ви можете робити event.target.dataset.tagабо event.target.getAttribute('data-tag'); або одна працює.


24
реагують 0,13,3, IE10 event.target.datasetне визначено, але event.target.getAttribute('data-tag')працює. інші браузери чудово. Спасибі
Андрій Борисько

Чи щось не так у цьому підході? Наприклад, залежно від того, яку кнопку натискає користувач, я хочу передати рядок функції. Я сподівався уникнути внесення трьох функцій у свій компонент для кожного випадку.
Майкл Дж. Калкінс

4
Ця відповідь краща за прийняту в плані ефективності. Це робити таким чином, що ми не створюємо нову функцію для кожного візуалізації. Він не тільки пропускає, створюючи нову функцію кожного рендерінгу, але оскільки посилання на функцію буде однаковим кожен раз, чисті (або запам'ятовані) компоненти не побачать її як іншу функцію. Таким чином, це не буде зайвим чином рендерингувати весь компонент кожен раз. Навіть спеціальна реалізація shouldComponentUpdateматиме те саме питання, якщо ви просто повністю не проігнорували функцію підтримки.
Михайло

Працює чудово
Огбонна Віталіс

1
Я використовую машинопис. У моєму випадку мені довелося скористатисяevent.currentTarget.getAttibute('data-tag')
karianpour

50

Ось найкращий спосіб, який я знайшов:

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

Ці атрибути зберігаються у "NamedNodeMap", до якого ви можете легко отримати доступ методом getNamedItem.


4
Ймовірно, ви хочете додати .value
атрибут,

Я відредагував відповідь, щоб додати .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

як ви знаєте, що внутрішня функція буде містити аргументи події?
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
Звідки походить "я"?
Freshchris

2
iє спеціальним атрибутом, який OP хотів якось передати. Це певна змінна, яка знаходиться в області застосування, коли aелемент визначений.
tytk

Це не те, чого хоче ОП. Вони хочуть отримати доступ до значення атрибута для елемента (a) за допомогою обробника onClick.
Дизайн Адріана

1
Моя думка полягала в тому, що офіційним рішенням є визначення функції обробника подій зі змінною за обсягом, а не встановлення атрибута даних на елементі. Це не заважає вам отримувати доступ до атрибутів елементів, якщо ви дійсно хочете, але це не ідіоматичний спосіб доступу до змінної в React.
tytk

8
<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працює для мене




3

Я не знаю про React, але в загальному випадку ви можете передавати власні атрибути на зразок цього:

1) визначити всередині html-тегу новий атрибут із префіксом даних

data-mydatafield = "asdasdasdaad"

2) отримати з javascript з

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

Продовжуйте вимовляти null
Si8

3

Якщо хтось намагається використати event.target у React і знайти нульове значення, це тому, що SyntheticEvent замінив event.target. SyntheticEvent тепер містить "currentTarget", наприклад, у event.currentTarget.getAttribute ("дані-ім'я користувача").

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

виглядає як чудовий коментар! як я можу побачити, що це набагато повільніше присвоює властивості будинку
Ido

2

Ви можете просто використовувати об'єкт event.target.dataset . Це дасть вам об'єкт з усіма атрибутами даних.


0

У React вам не потрібні дані HTML, використовуйте функцію повернення іншої функції; як це дуже просто надіслати користувальницькі параметри, і ви можете отримати доступ до спеціальних даних та події.

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag: (i) => (event) => {
    this.setState({inputVal: i}); 
},
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.