为什么通过JS向HTML文档添加`svg`标签时需要使用`document.createElementNS`?

6 javascript svg xml-namespaces

这是行不通的:

const svg = document.createElement('svg')
svg.setAttribute('height', '100')
svg.setAttribute('width', '100')
document.body.appendChild(svg)

const rect = document.createElement('rect')
rect.setAttribute('height', '100%')
rect.setAttribute('width', '100%')
rect.setAttribute('fill', 'red')
svg.appendChild(rect)
Run Code Online (Sandbox Code Playgroud)

这将起作用:

const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
svg.setAttribute('height', '100')
svg.setAttribute('width', '100')
document.body.appendChild(svg)

const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
rect.setAttribute('height', '100%')
rect.setAttribute('width', '100%')
rect.setAttribute('fill', 'red')
svg.appendChild(rect)
Run Code Online (Sandbox Code Playgroud)

svg显然,每次通过 JS 创建标签或其任何后代时,我都需要明确指定名称空间。

Q1:为什么有必要这样做?引用标签上的 MDN 文档svg

注意xmlns仅 SVG 文档最外层的 svg 元素需要该属性。对于内部 svg 元素或内部 HTML 文档来说是不必要的。

好吧,我svg在这里嵌套了内部 HTML,所以这个xmlns属性不是必需的,不是吗?

Q2:这种情况可以避免吗?

document.createElementNS('http://www.w3.org/2000/svg', 'rect')每次都要用手打字,很烦人。

有没有更短的方法?

Rob*_*son 7

如果你调用 document.createElement("a")<a>它应该创建哪个?HTML 的还是 SVG 的?问题就在这里。同上脚本等。在appendChild步骤之前,您没有给浏览器任何猜测的机会,到那时就为时已晚了。

您可以通过innerHTML在没有命名空间的情况下执行此操作,因为它需要一个包含所有标记的字符串,以便浏览器可以一步解析和添加,从而推断出正确的命名空间。

或者只是创建一个包装函数

function createSVGElement(tag) {
  return document.createElementNS('http://www.w3.org/2000/svg', tag)
}
Run Code Online (Sandbox Code Playgroud)