【问题标题】:How can I render a <template /> tag with react?如何使用 react 渲染 <template /> 标签?
【发布时间】:2017-08-08 06:48:22
【问题描述】:

有时您可能需要从您的 React 应用中渲染 Web 组件。

Web 组件通常使用特殊的&lt;template&gt; ... &lt;/template&gt; 标记。 但是,如果我尝试用这样的反应来呈现这样的标记:

render() {
  return (
    <template>
      <div>some content</div>
    </template>
  )
}

那么我的网络组件不能正常工作。

【问题讨论】:

    标签: reactjs web-component jsx documentfragment


    【解决方案1】:

    原因是 JSX 所做的工作与 &lt;template /&gt; 标记的用途不同。模板标签的想法是不渲染其子标签,并且几乎像处理未解析的文本一样处理它(浏览器实际上解析它只是为了确保其有效的 html,但仅此而已)

    但是当你用 JSX 写这个时:

    return (
      <template>
        <div>some content</div>
      </template>
    )
    

    您基本上是在指示 react 创建一个 'template' 元素,然后创建一个 'div' 元素,然后将此 div 附加到 template 作为一个孩子。 p>

    所以在幕后会发生这种情况:

    const template = document.createElement('template')
    const div = document.createElement('div')
    const text = document.createTextNode('some text')
    div.appendChild(text)
    template.appendChild(div)
    

    但你想要的是将&lt;template /&gt; 的内容设置为字符串。你可以使用innerHTML


    解决方案

    一种解决方案是:

    render() {
      return (
        <template
          dangerouslySetInnerHTML={{
            __html: '<div>some content</div>'
          }}
        />
      )
    }
    

    现在您要求 react 将所有这些子标签创建为节点元素,但让浏览器决定如何处理它们。

    更好的解决方案

    您可能不想一直使用dangerouslySetInnerHTML。所以让我们创建一个辅助组件:

    function Template({ children, ...attrs }) {
      return (
        <template
          {...attrs}
          dangerouslySetInnerHTML={{ __html: children }}
        />
      );
    }
    

    现在任何时候您需要使用模板,您都可以像这样使用它:

    render() {
      return (
        <Template>
          {'<div>some content</div>'}
        </Template>
      )
    }
    

    不要忘记将内部内容放在引号中,因为它应该是一个字符串。

    【讨论】:

    • 如果模板包含脚本(恰好是我的用例),dangerouslySetInnerHTML 将不起作用。
    • 我也遇到了同样的问题! @Christophe 你找到解决方案了吗?
    • 我想我放弃了,但最有希望的路径是 Range.createContextualFragment(),它确实让脚本运行。可能与 Reactjs 参考一起使用。
    • 我通过将孩子们包裹在ReactDomServer.renderToString中解决了这个问题
    【解决方案2】:

    我知道这个问题已经有了答案,但我想还有另一个更简单的解决方案来创建 hoc(高阶组件)。

    只需像这样创建新的“组件”:

    // hoc/Template.js
    const template = props => props.children
    export default template
    

    然后你就可以在你的项目中这样使用它了:

    import './hoc/Template.js'
    
    ...
    
    render() {
      return (
        <Template>
          {'<div>some content</div>'}
        </Template>
      )
    }
    

    较新版本的 react 已经构建了这样的组件,因此您无需创建组件即可实现相同的目标。

    import { Fragment } from 'react'
    
    ...
    
    render() {
      return (
        <Fragment>
          {'<div>some content</div>'}
        </Fragment>
      )
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-07
      • 1970-01-01
      • 2018-06-16
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      • 2016-06-07
      相关资源
      最近更新 更多