网络浏览器似乎抛出 DOMException
当一个人使用setAttributeNS
时在<svg>
上元素设置 xmlns
属性。即
>>> s = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
<svg></svg>
>>> s.setAttributeNS(null, 'xmlns', '123')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
>>> s.setAttributeNS('http://www.w3.org/2000/svg', 'xmlns',
'http://www.w3.org/2000/svg')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
>>> s.setAttributeNS(null, 'xmlns', 'http://www.w3.org/2000/svg')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
Mozilla docs建议始终使用setAttributeNS
,但它没有提到这种可能性。因此,该建议似乎有一些警告。
DOM Level 2 spec上setAttributeNS
提供一些见解:
NAMESPACE_ERR: Raised if the qualifiedName is malformed, if the qualifiedName has a prefix and the namespaceURI is null, if the qualifiedName has a prefix that is "xml" and the namespaceURI is different from "http://www.w3.org/XML/1998/namespace", or if the qualifiedName is "xmlns" and the namespaceURI is different from "http://www.w3.org/2000/xmlns/".
因此,这个特殊的异常似乎是更广泛的可能失败的案例的一部分。目前尚不清楚这些案件是什么。
我正在编写 tko/Knockout 4.0,一个通用的 Web 框架,因此它应该支持 svg
以及核心 HTML 命名空间之外的其他标记。
遇到最多的问题来自xmlns
上svg
标签,所以它是 an issue 。我有worked around this通过专门检查是否 xmlns
正在设置并使用setAttribute
在这种情况下。
该解决方法似乎非常具体,我担心一般情况。是否有先例说明如何通常使用 setAttributeNS
处理设置属性和setAttribute
?
其他 Web 框架并没有很好地解决这个问题——它通常与其他逻辑混合在一起;我见过的最准确的提交是 angular ,但它并没有直接解决这个问题。
最佳答案
它不会涵盖所有情况,但这应该会大有帮助:
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))
}
}
}
如果遇到的属性是xmlns="http://www.w3.org/2000/svg"
,则会添加
.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg')
如果遇到的属性是 xml:space="preserve"
(SVG 编辑器经常使用的属性),则会添加该属性
.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve')
关于javascript - 通用库的 <svg> 的 setAttributeNS xmlns,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52571125/