Làm cách nào để truy cập các thuộc tính tùy chỉnh từ đối tượng sự kiện trong React?


214

React có thể hiển thị các thuộc tính tùy chỉnh như được mô tả tại http://facebook.github.io/react/docs/jsx-gotchas.html :

Nếu bạn muốn sử dụng một thuộc tính tùy chỉnh, bạn nên thêm tiền tố vào dữ liệu-.

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

Và đó là tin tuyệt vời ngoại trừ tôi không thể tìm cách truy cập nó từ đối tượng sự kiện, ví dụ:

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

Các phần tử và thuộc data-tính kết xuất trong html tốt. Các thuộc tính tiêu chuẩn như stylecó thể được truy cập là event.target.styletốt. Thay vì event.targettôi đã thử:

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

Không ai trong số này làm việc.


1
Có thể là một bình luận giúp ai đó, tôi phát hiện ra React 16.7 không đăng ký lại và cập nhật các thuộc tính html tùy chỉnh của thành phần nếu bạn chỉ thay đổi chúng trong một cửa hàng (từ redux) và gắn với thành phần. Điều này có nghĩa là thành phần có aria-modal=true, bạn đẩy các thay đổi (thành false) vào kho lưu trữ các thuộc tính aria / dữ liệu , nhưng không có gì khác được thay đổi (chẳng hạn như nội dung hoặc lớp hoặc các biến trong đó) vì ReactJs sẽ không cập nhật aria / dữ liệu attrs trong các thành phần đó. Tôi đã loay hoay cả ngày để nhận ra điều đó.
AlexNikonov

Câu trả lời:


171

Để giúp bạn có được kết quả mong muốn theo một cách khác với cách bạn đã hỏi:

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

Lưu ý bind() . Bởi vì đây là tất cả javascript, bạn có thể làm những việc tiện dụng như thế. Chúng tôi không còn cần phải đính kèm dữ liệu vào các nút DOM để theo dõi chúng.

IMO này sạch hơn nhiều so với việc dựa vào các sự kiện DOM.

Cập nhật tháng 4 năm 2017: Những ngày này tôi sẽ viết onClick={() => this.removeTag(i)}thay vì.bind


17
nhưng bạn không còn nhận được đối tượng sự kiện thông qua.
chovy

9
.... Tôi chưa thử nghiệm điều này, nhưng tôi cho rằng "đối tượng sự kiện" vẫn đang được thông qua. Nó chỉ KHÔNG ở cùng một chỉ số tham số trước đây. Liên kết theo kiểu như đã nêu ở trên giống như unshifting mảng đối số hàm . Nếu "đối tượng sự kiện" ở chỉ mục 0thì bây giờ nó sẽ ở chỉ mục 1.
Ryder Brooks

8
@chovy Bạn có thể nếu bạn cần nó. Chỉ cần làmremoveTag: function(i, evt) {
Jared Forsyth

8
Nó sạch hơn, nhưng tất cả các liên kết đó đều có hiệu năng nếu bạn thực hiện nhiều thao tác đó.
El Yobo


296

event.targetcung cấp cho bạn nút DOM gốc, sau đó bạn cần sử dụng API DOM thông thường để truy cập các thuộc tính. Dưới đây là tài liệu về cách thực hiện điều đó: Sử dụng các thuộc tính dữ liệu .

Bạn có thể làm một trong hai event.target.dataset.taghoặc event.target.getAttribute('data-tag'); một trong hai hoạt động.


24
phản ứng 0.13.3, IE10 event.target.datasetkhông xác định nhưng event.target.getAttribute('data-tag')hoạt động. Các trình duyệt khác đều ổn. Cảm ơn
Andrey Borisko

Có điều gì sai với cách tiếp cận này? Ví dụ, tùy thuộc vào nút nào mà người dùng đẩy tôi muốn truyền chuỗi cho hàm. Tôi đã hy vọng tránh làm cho ba chức năng trong thành phần của tôi cho mỗi trường hợp.
Michael J. Calkins

4
Câu trả lời này tốt hơn câu trả lời được chấp nhận về hiệu suất. Làm theo cách này có nghĩa là chúng tôi không tạo ra một chức năng mới trên mỗi kết xuất. Nó không chỉ bỏ qua việc tạo một chức năng mới mỗi lần kết xuất, mà vì tham chiếu chức năng sẽ giống nhau mỗi lần, các thành phần thuần túy (hoặc ghi nhớ) sẽ không xem nó là một chức năng khác. Do đó, nó sẽ không cần thiết phải kết xuất lại toàn bộ thành phần mỗi lần. Ngay cả một triển khai tùy chỉnh shouldComponentUpdatecũng sẽ có cùng một vấn đề trừ khi bạn hoàn toàn bỏ qua chức năng chống đỡ.
Michael Yaworski

Hoạt động hoàn toàn tốt
Ogbonna Vitalis

1
Tôi sử dụng bản thảo. Trong trường hợp của tôi, tôi đã phải sử dụngevent.currentTarget.getAttibute('data-tag')
karianpour

50

Đây là cách tốt nhất tôi tìm thấy:

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

Các thuộc tính này được lưu trữ trong "NamedNodeMap", mà bạn có thể truy cập dễ dàng bằng phương thức getNamedItem.


4
Bạn có thể muốn thêm một .valueđể có được giá trị thực tế
Wikunia

Tôi đã chỉnh sửa câu trả lời để thêm .valuevào cuối như @Wikunia đã đề xuất
fguillen

25

Hoặc bạn có thể sử dụng một bao đóng:

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
Cảm ơn, Tudor. Đã thử giải pháp của bạn và nó hoạt động ngay cả khi không ràng buộc. Tôi đã sử dụng nó để chuyển đổi các kiểu trên e.target.
andriy_sof

Làm thế nào để bạn biết một chức năng bên trong sẽ chứa sự kiện 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
thêm một số mô tả vào mã của bạn để làm cho người khác hiểu mã
Aniruddha Das

8

Kể từ React v16.1.1 (2017), đây là giải pháp chính thức: https://reactjs.org/docs/handling-events.html#passing-argument-to-event-handlers

TLDR: OP nên làm:

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

1
Cái 'tôi' đến từ đâu?
Freshchris

2
ilà thuộc tính tùy chỉnh mà OP muốn vượt qua bằng cách nào đó. Đó là một số biến trong phạm vi khi aphần tử được xác định.
tytk

Đó không phải là điều OP muốn. Họ muốn truy cập một giá trị thuộc tính trên phần tử (a) bằng trình xử lý onClick.
Thiết kế của Adrian

1
Quan điểm của tôi là giải pháp chính thức là xác định hàm xử lý sự kiện với biến trong phạm vi, thay vì đặt thuộc tính dữ liệu trên phần tử. Điều này không ngăn bạn truy cập các thuộc tính của các yếu tố nếu bạn thực sự muốn, nhưng đó không phải là cách thành ngữ để truy cập vào một biến trong React.
tytk

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

vì vậy e.currentTarget.attributes['tag'].valuelàm việc cho tôi


5

Bạn có thể truy cập các thuộc tính dữ liệu như thế này

event.target.dataset.tag

4

Dòng mã này đã giải quyết vấn đề cho tôi:

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

3

Tôi không biết về React, nhưng trong trường hợp chung, bạn có thể chuyển các thuộc tính tùy chỉnh như thế này:

1) xác định bên trong thẻ html một thuộc tính mới có tiền tố dữ liệu

data-mydatafield = "asdasdasdaad"

2) nhận từ javascript với

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

Của tôi cứ nói null
Si8

3

Nếu bất cứ ai đang cố gắng sử dụng event.target trong React và tìm giá trị null, thì đó là bởi vì TotalEvent đã thay thế event.target. Hiện tại, TotalEvent giữ 'currentTarget', chẳng hạn như trong event.cienTarget.getAttribution ('data-username').

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

Có vẻ như React thực hiện điều này để nó hoạt động trên nhiều trình duyệt hơn. Bạn có thể truy cập các thuộc tính cũ thông qua thuộc tính localEvent.


3

Hãy thử thay vì gán các thuộc tính dom (chậm), chỉ cần chuyển giá trị của bạn dưới dạng tham số cho hàm thực sự tạo trình xử lý của bạn:

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

Trông giống như một bình luận tuyệt vời! làm thế nào tôi có thể thấy rằng việc gán thuộc tính dom chậm hơn nhiều
Ido Ble Rich

2

Bạn chỉ có thể sử dụng đối tượng event.target.dataset . Điều này sẽ cung cấp cho bạn đối tượng với tất cả các thuộc tính dữ liệu.


0

Trong React bạn không cần dữ liệu html, sử dụng hàm trả về hàm khác; như thế này rất đơn giản gửi thông số tùy chỉnh và bạn có thể tích lũy dữ liệu tùy chỉnh và sự kiện.

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag: (i) => (event) => {
    this.setState({inputVal: i}); 
},
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.