Bagaimana cara mengakses atribut khusus dari objek acara di Bereaksi?

214

Bereaksi mampu membuat atribut khusus seperti yang dijelaskan di http://facebook.github.io/react/docs/jsx-gotchas.html :

Jika Anda ingin menggunakan atribut khusus, Anda harus awalan dengan data-.

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

Dan itu berita bagus kecuali saya tidak dapat menemukan cara untuk mengaksesnya dari objek acara misalnya:

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

Elemen dan data-properti membuat html baik-baik saja. Properti standar seperti styledapat diakses dengan event.target.stylebaik. Alih-alih event.targetsaya mencoba:

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

tidak ada yang berhasil.

andriy_sof
sumber
1
Mungkin satu komentar membantu seseorang, saya menemukan Bereaksi 16.7 tidak membuat rerender dan memperbarui atribut html kustom komponen jika Anda hanya mengubahnya di toko (fe redux) dan terkait dengan komponen. Ini berarti komponen memiliki fitur aria-modal=true, Anda mendorong perubahan (ke false) ke penyimpanan atribut aria / data , tetapi tidak ada yang lain yang diubah (seperti konten komponen atau kelas atau variabel di sana) karena hasilnya ReactJs tidak akan memperbarui aria / attr data dalam komponen itu. Saya telah bermain-main sepanjang hari untuk menyadari hal itu.
AlexNikonov

Jawaban:

171

Untuk membantu Anda mendapatkan hasil yang diinginkan dengan cara yang mungkin berbeda dari yang Anda tanyakan:

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

Perhatikan bind() . Karena ini semua javascript, Anda dapat melakukan hal-hal praktis seperti itu. Kami tidak perlu lagi melampirkan data ke node DOM untuk melacaknya.

IMO ini jauh lebih bersih daripada mengandalkan acara DOM.

Perbarui April 2017: Hari-hari ini saya akan menulis onClick={() => this.removeTag(i)}sebagai ganti.bind

Jared Forsyth
sumber
17
tetapi Anda tidak lagi mendapatkan objek acara berlalu.
chovy
9
@chovy Harap perbaiki saya jika saya salah tetapi tidak semua fungsi javascript inheren variadic? Saya belum menguji ini, tapi saya akan menganggap "objek acara" masih dilewati. Hanya saja TIDAK pada indeks parameter yang sama seperti sebelumnya. Mengikat dengan cara seperti diuraikan di atas adalah seperti unshifting array argumen fungsi . Jika "objek acara" berada di indeks 0sekarang akan di indeks 1.
Ryder Brooks
8
@ chovy Anda bisa jika Anda membutuhkannya. Lakukan sajaremoveTag: function(i, evt) {
Jared Forsyth
8
Ini lebih bersih, tetapi semua ikatan itu memiliki kinerja yang baik jika Anda melakukan banyak hal.
El Yobo
297

event.targetmemberi Anda simpul DOM asli, maka Anda perlu menggunakan DOM API biasa untuk mengakses atribut. Berikut adalah dokumen tentang cara melakukannya: Menggunakan atribut data .

Anda dapat melakukan salah satu event.target.dataset.tagatau event.target.getAttribute('data-tag'); salah satu yang berfungsi.

Sophie Alpert
sumber
24
bereaksi 0.13.3, IE10 event.target.datasettidak didefinisikan tetapi event.target.getAttribute('data-tag')berfungsi. browser lainnya baik-baik saja. Terima kasih
Andrey Borisko
Apakah ada yang salah dengan pendekatan ini? Misalnya tergantung pada tombol apa yang ditekan pengguna, saya ingin meneruskan sebuah string ke suatu fungsi. Saya berharap untuk tidak membuat tiga fungsi dalam komponen saya untuk setiap kasus.
Michael J. Calkins
4
Jawaban ini lebih baik daripada yang diterima dalam hal kinerja. Melakukannya dengan cara ini berarti bahwa kami tidak membuat fungsi baru pada setiap render. Tidak hanya melompati pembuatan fungsi baru setiap render, tetapi karena referensi fungsi akan sama setiap kali, komponen murni (atau memoized) tidak akan melihatnya sebagai fungsi yang berbeda. Oleh karena itu, itu tidak akan perlu merender ulang seluruh komponen setiap saat. Bahkan implementasi kustom shouldComponentUpdateakan memiliki masalah yang sama kecuali jika Anda hanya mengabaikan prop fungsi.
Michael Yaworski
Bekerja dengan sangat baik
Ogbonna Vitalis
1
Saya menggunakan naskah. Dalam kasus saya, saya harus menggunakanevent.currentTarget.getAttibute('data-tag')
karianpour
50

Inilah cara terbaik yang saya temukan:

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

Atribut tersebut disimpan dalam "NamedNodeMap", yang dapat Anda akses dengan mudah dengan metode getNamedItem.

roctimo
sumber
4
Anda mungkin ingin menambahkan .valueuntuk mendapatkan nilai aktual
Wikunia
Saya telah mengedit jawaban untuk menambahkan .valuedi bagian akhir seperti yang disarankan
@Wikunia
25

Atau Anda dapat menggunakan penutupan:

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 
}
Tudor Campean
sumber
3
Terima kasih, Tudor. Mencoba solusi Anda dan itu berfungsi bahkan tanpa mengikat. Saya menggunakannya untuk beralih gaya di e.target.
andriy_sof
bagaimana Anda tahu fungsi dalam akan berisi argumen acara?
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>
Mentori
sumber
1
tambahkan beberapa deskripsi ke kode Anda untuk membuat orang lain memahami kode
Aniruddha Das
8

Pada React v16.1.1 (2017), berikut adalah solusi resmi: https://reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers

TLDR: OP harus melakukan:

render: function() {
...
<a style={showStyle} onClick={(e) => this.removeTag(i, e)}></a>
...
removeTag: function(i, event) {
    this.setState({inputVal: i}); 
}
tytk
sumber
1
Dari mana 'i' berasal?
Freshchris
2
iadalah atribut khusus yang OP ingin sampaikan. Ini beberapa variabel yang ada dalam ruang lingkup ketika aelemen didefinisikan.
tytk
Bukan itu yang diinginkan OP. Mereka ingin mengakses nilai atribut pada elemen (a) dengan penangan onClick.
Desain oleh Adrian
1
Maksud saya adalah bahwa solusi resmi adalah untuk menentukan fungsi event-handler dengan variabel dalam lingkup, daripada menetapkan atribut data pada elemen. Ini tidak menghentikan Anda dari mengakses atribut elemen jika Anda benar-benar ingin, tetapi itu bukan cara idiomatis untuk mengakses variabel di Bereaksi.
tytk
8
<div className='btn' onClick={(e) =>
     console.log(e.currentTarget.attributes['tag'].value)}
     tag='bold'>
    <i className='fa fa-bold' />
</div>

jadi e.currentTarget.attributes['tag'].valuebekerja untuk saya

Manindra Gautam
sumber
5

Anda dapat mengakses atribut data seperti ini

event.target.dataset.tag
Rameez Iqbal
sumber
4

Baris kode tunggal ini memecahkan masalah bagi saya:

event.currentTarget.getAttribute('data-tag')
Emeka Augustine
sumber
3

Saya tidak tahu tentang Bereaksi, tetapi dalam kasus umum Anda dapat memberikan atribut khusus seperti ini:

1) mendefinisikan di dalam html-tag atribut baru dengan awalan data

data-mydatafield = "asdasdasdaad"

2) dapatkan dari javascript dengan

e.target.attributes.getNamedItem("data-mydatafield").value 
jimver04
sumber
Milik
3

Jika ada yang mencoba menggunakan event.target di Bereaksi dan menemukan nilai nol, itu karena SyntheticEvent telah menggantikan event.target. SyntheticEvent sekarang memiliki 'currentTarget', seperti di event.currentTarget.getAttribute ('data-username').

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

Sepertinya React melakukan ini sehingga berfungsi di lebih banyak browser. Anda dapat mengakses properti lama melalui atribut nativeEvent.

Eduardo
sumber
3

Coba alih-alih menetapkan properti dom (yang lambat) cukup berikan nilai Anda sebagai parameter untuk berfungsi yang sebenarnya membuat penangan Anda:

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag = (customAttribute) => (event) => {
    this.setState({inputVal: customAttribute});
}
msangel
sumber
sepertinya komentar yang bagus! bagaimana saya bisa melihat bahwa itu jauh lebih lambat menetapkan properti dom
Ido Bleicher
2

Anda cukup menggunakan objek event.target.dataset . Ini akan memberi Anda objek dengan semua atribut data.

Vikash Kumar
sumber
0

Di Bereaksi Anda tidak memerlukan data html, gunakan fungsi untuk mengembalikan fungsi lainnya; seperti ini, sangat sederhana kirim params khusus dan Anda dapat mengakses data khusus dan acara.

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