问题 如何在React中呈现HTML注释?


目前,render方法只能返回单个元素/组件。看到: 这里

在该票据的讨论中,一些人建议在HTML注释中包装从React组件返回的多个元素,以便浏览器忽略包装组件,例如:

<A>
    <B></B>
    <Fragment>
        <C></C>
        <D></D>
    </Fragment>
    <E></E>
</A>

会呈现给:

<a>
    <b></b>
    <!--<fragment data-reactid="">-->
        <c></c>
        <d></d>
    <!--</fragment>-->
    <e></e>
</a>

但是如何实际创建一个只呈现HTML注释的组件?换句话说,上面例子中'fragment'组件的render函数如何看起来像?


4587
2017-10-13 07:57


起源

发布该评论的人不理解React的工作原理。请注意,建议它的人都不会工作。首先,它没有解决核心问题;结果是四个节点(注释节点,两个元素节点,然后是注释节点),而不是单个节点。 - T.J. Crowder
我的理解是Fragment的render函数只返回带有两个子组件'c'和'd'的Fragment组件。因此第二个注释中的结束标记'/ fragment'。此外,似乎该技术已用于在提交dcc972c414中的mwiencek / react fork中实现片段组件,但我可能错了。 - Amiramix


答案:


这是我最近的一个项目中最终得到的结果:

import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';

class ReactComment extends Component {
    static propTypes = {
        text: PropTypes.string,
        trim: PropTypes.bool
    };

    static defaultProps = {
        trim: true
    };

    componentDidMount() {
        let el = ReactDOM.findDOMNode(this);
        ReactDOM.unmountComponentAtNode(el);
        el.outerHTML = this.createComment();
    }

    createComment() {
        let text = this.props.text;

        if (this.props.trim) {
            text = text.trim();
        }

        return `<!-- ${text} -->`;
    }

    render() {
        return <div />;
    }
}

export default ReactComment;

所以你可以像这样使用它:

<A>
    <B></B>
    <ReactComment text="<fragment>" />
        <C></C>
        <D></D>
     <ReactComment text="</fragment>" />
    <E></E>
</A>

11
2017-12-13 22:02



谢谢,但据我了解这段代码,它没有回答我的问题。我的目的不是在React中呈现注释,而是从呈现函数返回单个元素,该元素呈现两个注释,一个在其上面,一个在其子项下面。换句话说,我应该能够像这样使用它: <Fragment><C /><D /></Fragment> 它应该为孩子们提供两个评论,一个在上面,一个在下面,就像我的问题中的例子一样。 - Amiramix


编辑: 对于那些发现这个答案有用的人,结帐 这个答案 代替!

发布的问题不是要求React中的评论风格!


使用大括号,这样您就可以使用javascript注释 /* */

<a>
    <b></b>
    {/*<fragment data-reactid="">*/}
        <c></c>
        <d></d>
    {/*</fragment>*/}
    <e></e>
</a>

3
2018-05-15 05:20



6赞成答案,甚至没有提出问题的解决方案?!这就是如何在组件代码中添加注释,但是(像我一样)OP希望如此 产量 评论他的渲染的HTML! - Andy Lorenz


您计划这样做的方式不适用于简单的香草React解决方案。但是,您可以定义一个自定义Web组件,该组件可转换为HTML注释并从React包装器中返回。实现了一个示例组件 这里。有关在React中的用法,请参阅 这个网址

2017年1月19日更新

所以这是未经测试的理论,但网络组件可能是这样的 -

```

 /**
 * <react-comment-sentinel> Web Component
 *
 * @usage
 *  <react-comment-sentinel sentinel="fragment"><div>Hello there!</div></react-comment-sentinel>

 * @result
 *  <!-- <fragment> --><div>Hello there!</div><!-- </fragment> -->
 */
var proto = Object.create(HTMLElement.prototype, {
 name: { get: function() { return 'React HTML Comment'; } },
 createdCallback: { value: function() {

  /**
   * Firefox fix, is="null" prevents attachedCallback
   * @link https://github.com/WebReflection/document-register-element/issues/22
   */
  this.is = '';
  this.removeAttribute('is');
 } },
 attachedCallback: { value: function() {
  var tag = this.attributes("sentinel");
  this.outerHTML = '<!-- <' + tag + '> -->' + this.innerHtml + '<!-- </' + tag + '> -->';
 } }
});
document.registerElement('react-comment-sentinel', { prototype: proto });

```

请注意,内部子项是纯HTML,而不是React。但是,您可以尝试增强代码 支持React组件 太。


0
2018-01-18 13:15



嗨,据我所知,这将无法工作,因为注释组件需要呈现两个注释,一个在上面,一个在传递给它的子项下面,而不是在注释中呈现它的子项。 - Amiramix
我从问题中理解你的要求,但从技术上讲,html注释不是容器元素。你在这里有两个不同的评论。虽然你的例子有 <fragment> 标签和 </fragment> 包含在其中的标记,生成的标记仍然是四个独立的HTML元素,包括 C 和 D 组件。因此,不要试图将两个注释看作具有不同open和close标签的一个虚拟元素,而是将它们视为C和D的兄弟.XHTML对容器标签非常清楚,除了包含结束标记的标记外,标记必须相同 /。 - hazardous
我认为你不了解我的要求。我的目的不是呈现HTML注释,而是创建一个围绕React子元素的包装器组件,其中1.可以作为一个元素从render函数返回,2。呈现为HTML中的两个注释,一个在呈现的子元素之前,另一个在渲染的孩子之后。 - Amiramix