当浏览器在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
,但是没有提及这种可能性。因此,该建议似乎有一些警告。
setAttributeNS
上的DOM Level 2 spec提供了一些见解:
NAMESPACE_ERR:如果qualifiedName格式不正确,qualifiedName具有前缀且namespaceURI为null,qualifiedName具有前缀“ xml”且namespaceURI与“ http://www.w3.org/XML/1998/namespace”不同,则引发此错误,或者如果qualifiedName是“ xmlns”,并且namespaceURI与“ http://www.w3.org/2000/xmlns/”不同。
因此,该特殊异常似乎是可能失败的更广泛案件的一部分。这些情况是什么现在还不清楚。
我正在编写通用Web框架tko / Knockout 4.0,因此它应该支持svg
和核心HTML命名空间之外的其他标签。
最常遇到的问题来自xmlns
标签上的svg
,因此是an issue。我通过专门检查是否已设置xmlns
并在这种情况下使用setAttribute
来worked around this。
该解决方法似乎非常具体,我担心一般情况。关于通常如何使用setAttributeNS
和setAttribute
处理设置属性是否有先例?
其他Web框架不能很好地解决这个问题-它通常与其他逻辑混合在一起。我见过的最即时的提交是针对angular的,但是它并不能直接解决这个问题。
答案 0 :(得分:1)
它不会涵盖所有情况,但是应该走很长一段路:
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')