# React技巧之设置data属性
原文链接:https://bobbyhadz.com/blog/react-set-data-attribute (opens new window)
作者:Borislav Hadzhiev (opens new window)
正文从这开始~
# 总览
在React中,为元素设置data属性的话,直接在元素上设置属性即可。比如说,<button data-test-id="my-btn"> ,或者使用setAttribute() 方法。比如说,el.setAttribute('data-foo', 'bar') 。你可以在event对象上或者使用ref来访问元素。
export default function App() {
  const handleClick = event => {
    console.log(event.target.dataset);
    // 👇️ "my-btn"
    console.log(event.target.getAttribute('data-test-id'));
    // 👇️ set attribute
    event.target.setAttribute('data-foo', 'bar');
    console.log(event.target.getAttribute('data-foo')); // 👉️ bar
    event.target.setAttribute('data-foo', 'baz');
    console.log(event.target.getAttribute('data-foo')); // 👉️ baz
  };
  return (
    <div>
      {/* 👇️ set data-test-id attribute */}
      <button onClick={handleClick} data-test-id="my-btn">
        Click
      </button>
    </div>
  );
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
如果你需要通过
ref而不是通过event对象来访问元素,请往下翻阅。
# event对象
我们可以通过data-* 语法来直接在元素上设置data属性。
<button onClick={handleClick} data-test-id="my-btn">
  Click
</button>
 2
3
需要注意的是,我们不要驼峰命名自定义data-* 属性。
这个例子向我们展示了如何在事件中,以编程方式来使用setAttribute()方法进行设置或者更新data属性。
event.target.setAttribute('data-foo', 'bar');
 该方法接收以下两个参数:
name- 要设置的属性的名称。value- 赋值给属性的值。
如果属性已经存在于元素上,那么属性值将会被更新。否则将添加具有指定名称和值的新属性。
如果需要从元素上移除一个属性,可以使用removeAttribute方法。
el.removeAttribute('data-foo');
 removeAttribute方法从元素中删除具有指定名称的属性。如果元素上不存在该属性,那么此方法直接返回而不抛出错误。
event上面的target属性给了我们一个对触发事件的元素的引用(可以是后代元素)。
const handleClick = event => {
  console.log(event.target.dataset);
  // 👇️ "my-btn"
  console.log(event.target.getAttribute('data-test-id'));
  // 👇️ set attribute
  event.target.setAttribute('data-foo', 'bar');
  console.log(event.target.getAttribute('data-foo')); // 👉️ bar
  event.target.setAttribute('data-foo', 'baz');
  console.log(event.target.getAttribute('data-foo')); // 👉️ baz
};
 2
3
4
5
6
7
8
9
10
11
12
13
而
event上的currentTarget属性让我们访问事件监听器所连接的元素。
如果target属性在你的方案中指的是一个子元素,而你需要访问事件监听器所连接的元素,只需用currentTarget替换target。
const handleClick = event => {
  console.log(event.currentTarget.dataset);
  // 👇️ "my-btn"
  console.log(event.currentTarget.getAttribute('data-test-id'));
  // 👇️ set attribute
  event.currentTarget.setAttribute('data-foo', 'bar');
  console.log(event.currentTarget.getAttribute('data-foo')); // 👉️ bar
  event.currentTarget.setAttribute('data-foo', 'baz');
  console.log(event.currentTarget.getAttribute('data-foo')); // 👉️ baz
};
 2
3
4
5
6
7
8
9
10
11
12
13
# useRef
另外,你也可以使用ref来访问DOM元素,来设置其data属性。
import {useRef} from 'react';
export default function App() {
  const ref = useRef(null);
  const handleClick = () => {
    console.log(ref.current.dataset);
    // 👇️ "my-btn"
    console.log(ref.current.getAttribute('data-test-id'));
    // 👇️ set attribute
    ref.current.setAttribute('data-foo', 'bar');
    console.log(ref.current.getAttribute('data-foo')); // 👉️ bar
    ref.current.setAttribute('data-foo', 'baz');
    console.log(ref.current.getAttribute('data-foo')); // 👉️ baz
  };
  return (
    <div>
      <button ref={ref} onClick={handleClick} data-test-id="my-btn">
        Click
      </button>
    </div>
  );
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
上面示例实现的结果都是相同的,只不过我们使用了ref来访问DOM元素。
useRef()钩子可以传递一个初始值作为参数。该钩子返回一个可变ref对象,其.current属性被初始化为传递的参数。
需要注意的是,我们必须访问
ref对象上的current属性,才能访问设置了ref属性的button元素。
当我们为元素传递ref属性时,比如说,<button ref={myRef} /> ,React将ref对象上的.current属性设置为对应的DOM节点。
ref上的current属性可以让我们访问button元素,所以我们可以在元素上使用如下方式来设置data属性,ref.current.setAttribute('data-foo', 'bar') 。
请确保在useEffect钩子内部或者事件发生时访问ref 。因为如果尝试立即访问ref的话,它也许尚未建立,或者当前元素还不存在于DOM中。