如何使用 react 渲染 <template /> 标签?

Posted

技术标签:

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

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

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

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

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

【问题讨论】:

【参考方案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>
  )

【讨论】:

以上是关于如何使用 react 渲染 <template /> 标签?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 map 和 join 渲染 React 组件?

如何使用 ReactDOM Render 渲染一个 React 组件

react-redux:在 API 调用后渲染组件

如何添加将使用 react-router-dom 渲染组件的路由?

如何在 React Native 中使用函数渲染组件

如何使用 vue-cli 将数据渲染到 DOM