通用库的 <svg> 的 setAttributeNS xmlns

Bri*_*unt 3 javascript xml svg dom

DOMException当使用setAttributeNS元素<svg>设置属性时,网络浏览器似乎会抛出 a xmlns。IE

\n\n
>>> s = document.createElementNS(\'http://www.w3.org/2000/svg\', \'svg\')\n<svg>\xe2\x80\x8b</svg>\xe2\x80\x8b\n\n>>> s.setAttributeNS(null, \'xmlns\', \'123\')\nUncaught DOMException: Failed to execute \'setAttributeNS\' \n  on \'Element\': \'\' is an invalid namespace for attributes.\n\n>>> s.setAttributeNS(\'http://www.w3.org/2000/svg\', \'xmlns\', \n      \'http://www.w3.org/2000/svg\')\nUncaught DOMException: Failed to execute \'setAttributeNS\' \n  on \'Element\': \'\' is an invalid namespace for attributes.\n\n>>> s.setAttributeNS(null, \'xmlns\', \'http://www.w3.org/2000/svg\')\nUncaught DOMException: Failed to execute \'setAttributeNS\' \n  on \'Element\': \'\' is an invalid namespace for attributes.\n
Run Code Online (Sandbox Code Playgroud)\n\n

Mozilla文档建议始终使用setAttributeNS,但它没有提及这种可能性。因此,该建议似乎有一些警告。

\n\n

DOM Level 2 规范给出setAttributeNS了一些见解:

\n\n
\n

NAMESPACE_ERR:如果qualifiedName 格式错误,如果qualifiedName 有前缀且namespaceURI 为空,如果qualifiedName 有前缀“xml”且namespaceURI 与“ http://www.w3.org/XML不同”,则引发该错误/1998/namespace ”,或者如果qualifiedName 是“xmlns”并且namespaceURI 与“ http://www.w3.org/2000/xmlns/ ”不同。

\n
\n\n

因此,这个特殊的例外似乎是更广泛的可能失败案例的一部分。目前尚不清楚这些案件是什么。

\n\n

我正在编写 tko / Knockout 4.0,一个通用的 Web 框架,因此它应该支持svg核心 HTML 命名空间之外的其他标签。

\n\n

最常遇到的问题来自xmlns标签svg,因此这是一个问题。我已经通过专门检查是否正在设置并在这种情况下使用来解决问题。xmlnssetAttribute

\n\n

该解决方法似乎非常具体,我担心一般情况。是否有一般如何处理使用setAttributeNS和设置属性的先例setAttribute

\n\n

其他 Web 框架并没有很好地解决这个问题,\xe2\x80\x94 它通常与其他逻辑混合在一起;我见过的最准确的提交是针对Angular的,但它并没有直接解决这个问题。

\n\n

相关:setAttribute 和 setAttributeNS(null,

\n

ccp*_*rog 6

它不会涵盖所有情况,但这应该会大有帮助:

const NAMESPACES = {
  svg: 'http://www.w3.org/2000/svg',
  html: 'http://www.w3.org/1999/xhtml',
  xml: 'http://www.w3.org/XML/1998/namespace',
  xlink: 'http://www.w3.org/1999/xlink',
  xmlns: 'http://www.w3.org/2000/xmlns/' // sic for the final slash...
}

class JsxObserver extends LifeCycle {
  ...

  setNodeAttribute (node, name, valueOrObservable) {
    const value = unwrap(valueOrObservable)
    NativeProvider.addValueToNode(node, name, valueOrObservable)
    if (value === undefined) {
      node.removeAttributeNS(null, name)
    } else if (isThenable(valueOrObservable)) {
      Promise.resolve(valueOrObservable)
        .then(v => this.setNodeAttribute(node, name, v))
    } else {
      const [prefix, ...unqualifiedName] = name.split(':')
      let ns = null
      if (prefix === 'xmlns' || unqualifiedName.length && NAMESPACES[prefix]) {
        ns = NAMESPACES[prefix]
      }
      node.setAttributeNS(ns, name, String(value))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果遇到的属性是xmlns="http://www.w3.org/2000/svg",则会添加

.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg')
Run Code Online (Sandbox Code Playgroud)

如果遇到的属性是xml:space="preserve"(SVG 编辑器众所周知使用的属性),则会添加

.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve')
Run Code Online (Sandbox Code Playgroud)