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

tim*_*der 5 jsx documentfragment web-component reactjs

有时您可能需要从您的反应应用程序渲染Web组件.

Web组件通常使用特殊<template> ... </template>标记.但是,如果我尝试使用这样的反应来渲染这样的标记:

render() {
  return (
    <template>
      <div>some content</div>
    </template>
  )
}
Run Code Online (Sandbox Code Playgroud)

然后我的网络组件无法正常工作.

tim*_*der 7

原因是JSX与<template />标签存在的工作不同.模板标签的想法是不渲染它的子节点,并且几乎像未解析的文本一样处理它(浏览器实际上解析它只是为了确保其有效的html,但不做任何其他事情)

但是当你在JSX中写这个:

return (
  <template>
    <div>some content</div>
  </template>
)
Run Code Online (Sandbox Code Playgroud)

你基本上是指示创建'template'元素的反应,然后创建一个'div'元素,然后将其附加divtemplate孩子身上.

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

const template = document.createElement('template')
const div = document.createElement('div')
const text = document.createTextNode('some text')
div.appendChild(text)
template.appendChild(div)
Run Code Online (Sandbox Code Playgroud)

但你想要的是将<template />字符串的内容设置为.你可以用innerHTML它.


一个解决方案是:

render() {
  return (
    <template
      dangerouslySetInnerHTML={{
        __html: '<div>some content</div>'
      }}
    />
  )
}
Run Code Online (Sandbox Code Playgroud)

现在你要求做出反应,将所有这些子标签创建为节点元素,但让浏览器决定如何处理它们.

更好的解决方案

您可能不想一直使用dangerouslySetInnerHTML.那么让我们创建一个帮助组件:

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

现在,只要您需要使用模板,就可以像这样使用它:

render() {
  return (
    <Template>
      {'<div>some content</div>'}
    </Template>
  )
}
Run Code Online (Sandbox Code Playgroud)

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