如何在JSX中添加自定义HTML属性

96

有不同的原因,但我想知道如何在JSX中简单地向元素添加自定义属性?


也许这条评论能帮助到某些人,我发现 React 16.7 如果你只是在 store(例如 redux)中更改了组件的 HTML 属性并将其绑定到组件上,则不会重新渲染和更新组件的 HTML 属性。这意味着如果组件有aria-modal=true,你将更改(变为 false)存储在 aria/data 属性的 store 中,但是除此之外没有任何其他更改(例如组件的内容、类或其中的变量),因此 ReactJs 将不会更新该组件中的 aria/data 属性。我已经研究了整整一天才意识到这一点。 - Alexey Nikonov
11个回答

93

编辑:已更新以反映React 16

在React 16中,本地支持自定义属性。这意味着将自定义属性添加到元素现在就像将它添加到render函数一样简单:

render() {
  return (
    <div custom-attribute="some-value" />
  );
}

更多信息请参见:
https://reactjs.org/blog/2017/09/26/react-v16.0.html#support-for-custom-dom-attributes
https://facebook.github.io/react/blog/2017/09/08/dom-attributes-in-react-16.html


以前的答案(React 15及更早版本)

目前不支持自定义属性。有关更多信息,请参见此开放问题:https://github.com/facebook/react/issues/140

作为一种解决方法,您可以在componentDidMount中执行以下操作:

componentDidMount: function() {
  var element = ReactDOM.findDOMNode(this.refs.test);
  element.setAttribute('custom-attribute', 'some value');
}

请查看https://jsfiddle.net/peterjmag/kysymow0/,其中有一个可运行的示例。(灵感来自于syranide在此评论中的建议。)


是的,我想只有这种方式了。不过,这种方法看起来很有趣。 - Andrey Borisko
1
我是一个完全不懂React的新手,所以如果这个问题很愚蠢,请见谅。但为什么不直接在ref回调中添加所有自定义属性呢?例如:ref={(thisSvgElement) => { thisSvgElement.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); }} - k7n4n5t3w4rt
@k7n4n5t3w4rt,没错,那也可以。当我写这个答案的时候,回调函数还不存在。 - peterjmag
1
这并非完全正确。您可以通过在自定义属性之前加上“data-”或“aria-”来添加自定义属性。请参见Luca的答案和/或React文档 - Scott
为什么不能在组件上这样做,以便attr将呈现在渲染的第一个元素上? - Nikos

61

您可以使用ES6展开运算符添加属性,例如:

let myAttr = {'data-attr': 'value'}

并在渲染方法中:

<MyComponent {...myAttr} />

2
如果你的项目中有 ES6 转译器,它就可以工作。 - Spadar Shut
2
好的,这里有一个 codepen 示例。我没有看到自定义属性。 - Andrey Borisko
6
@AndreyBorisko - 我本打算提到但遗漏了,除非前缀为data-,否则无效的html属性和自定义属性现在将不起作用。 - DDM
1
我认为这个答案是误导性的,因为问题特定于自定义属性,@peterjmag提出的解决方案才是正确的。 - Kevin Farrugia
@KevinFarrugia,数据属性仍然是自定义属性,通过element.setAttribute('custom-attribute', 'some value');向DOM添加属性根本不是JSX。 - Spadar Shut
显示剩余3条评论

29

如果你想传递一个名为myAttr的自定义属性,值为myValue,那么这将起作用:

<MyComponent data-myAttr={myValue} />

2
@GusDeCool 首先声明,此代码已经在 react 15.3.1 版本下测试过,因此您的反对意见并没有任何意义,因为您抱怨它无法与 15.5.4 版本兼容。其次,我刚刚使用了 ^15.6.1 进行了测试,它可以正常工作。请仔细检查您的代码。 - Luca Fagioli
2
啊,我明白了,它在 react-dom 上而不是 react。抱歉,是我的错 :)。 - GusDeCooL
4
这是正确的答案。你可以通过在属性名前加上data-aria-来添加自定义属性。参见:https://facebook.github.io/react/docs/dom-elements.html - Scott
React 16及以上版本 - Morris S
1
这感觉像是最符合 HTML5 标准的答案。 - jcollum
@MorrisS 这不正确,因为自React 15.6.x以来它实际上是有效的。 - Luca Fagioli

13

如果您正在使用ES6,那么这应该可以工作:

<input {...{ "customattribute": "somevalue" }} />

你真是个天才!谢谢。 - Aminadav Glickshtein

12
你可以使用"is"属性来禁用元素的React属性白名单。
查看我的答案: Stackoverflow

5
我在尝试使用SVG和React时经常遇到这个问题。最终我采用了一种相当不好的解决方法,但知道这个选项是有用的。以下是允许在SVG元素上使用vector-effect属性的代码:
import SVGDOMPropertyConfig from 'react/lib/SVGDOMPropertyConfig.js';
import DOMProperty from 'react/lib/DOMProperty.js';

SVGDOMPropertyConfig.Properties.vectorEffect = DOMProperty.injection.MUST_USE_ATTRIBUTE;
SVGDOMPropertyConfig.DOMAttributeNames.vectorEffect = 'vector-effect';

只要在使用React之前包含/导入此内容,它就应该能够正常工作。

有趣。我会去看看。 - Andrey Borisko

3

点击事件中在控制台查看属性值

//...
   alertMessage (cEvent){
           console.log(cEvent.target.getAttribute('customEvent')); /*display attribute value */
        }
//...

在渲染方法中,您可以根据自己的需要添加 customAttribute 来定制属性。

render(){
    return <div>
//..
    <button customAttribute="My Custom Event Message" onClick={this.alertMessage.bind(this) } >Click Me</button>
            </div>
        }
//...

2

uniqueId是自定义属性。

<a {...{ "uniqueId": `${item.File.UniqueId}` }}  href={item.File.ServerRelativeUrl} target='_blank'>{item.File.Name}</a>

2
根据您使用的React版本不同,您可能需要使用类似于这样的内容。我知道Facebook正在考虑在不久的将来弃用字符串引用。
var Hello = React.createClass({
    componentDidMount: function() {
        ReactDOM.findDOMNode(this.test).setAttribute('custom-attribute', 'some value');
    },
    render: function() {
        return <div>
            <span ref={(ref) => this.test = ref}>Element with a custom attribute</span>
        </div>;
    }
});

React.render(<Hello />, document.getElementById('container'));

Facebook的参考文档


1

根据阻止您执行此操作的具体原因,还有另一种选项,无需更改当前实现。您应该能够在项目中使用.ts.d.ts文件(不确定哪个)来增强React。它看起来应该是这样的:

declare module 'react' {
    interface HTMLAttributes<T> extends React.DOMAttributes<T> {
        'custom-attribute'?: string; // or 'some-value' | 'another-value'
    }
}

另一种可能性是以下内容:

declare namespace JSX {
    interface IntrinsicElements {
        [elemName: string]: any;
    }
}

查看JSX | 类型检查

你甚至可能需要将其包装在declare global {中。我还没有最终解决方案。

另请参阅:如何在TypeScript/JSX中向现有HTML元素添加属性?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接