javascript - setAttributeNS xmlns 的
问题描述
DOMException
当使用元素设置属性时setAttributeNS
,Web 浏览器似乎会抛出一个错误。IE<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 文档建议始终使用,setAttributeNS
但它没有提到这种可能性。因此,该建议似乎有一些警告。
DOM Level 2 规范给出了一些setAttributeNS
见解:
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/ ”。
所以这个特殊的例外似乎是更广泛的可能失败的案例的一部分。目前还不清楚这些案例是什么。
我正在编写 tko / Knockout 4.0,一个通用的 Web 框架,因此它应该支持svg
核心 HTML 命名空间之外的其他标签。
最常遇到的问题来自xmlns
于svg
标签,所以这是一个问题。我已经通过专门检查是否在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')
推荐阅读
- django - 如何将 React 与 Django 连接起来?
- reactjs - 你应该防止在渲染代码中映射/过滤数组吗?
- powershell - 我们如何检查价值 $new_value1 = $inputpecentw1.Text。这个值可以吗?
- android - Android Studio 3.5.2 androidx 测试成为未解决的参考
- jenkins - 在Jenkins文件中一次注释掉多行的快捷方式是什么?
- php - Symfony 在 CLI 命令中捕获 PHP 错误
- android - Kotlin 异常:指定为非 null 的参数为 null
- php - 无法使用 HTML 读取网页上的 Mysql 数据
- javascript - 用户可以有意或通过随机生成填充两个相关的 div — 如何将选定的值存储在本地存储中?
- azure - 使用 Terraform 更新 Azure KeyVault 的防火墙规则