jQuery 3 没有这个问题
jQuery 3.0 修订版中列出的更改之一是:
添加SVG类的操作(#2199,20aaed3)
这个问题的一个解决方案是升级到 jQuery 3。它工作得很好:
var flip = true;
setInterval(function() {
// Could use toggleClass, but demonstrating addClass.
if (flip) {
$('svg circle').addClass('green');
}
else {
$('svg circle').removeClass('green');
}
flip = !flip;
}, 1000);
svg circle {
fill: red;
stroke: black;
stroke-width: 5;
}
svg circle.green {
fill: green;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<svg>
<circle cx="50" cy="50" r="25" />
</svg>
问题:
jQuery 类操作函数不适用于 SVG 元素的原因是因为 3.0 之前的 jQuery 版本使用className
这些函数的属性。
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ) :
" "
);
这对于 HTML 元素的行为符合预期,但对于 SVG 元素className
则略有不同。对于 SVG 元素,className
不是字符串,而是SVGAnimatedString
.
考虑以下代码:
var test_div = document.getElementById('test-div');
var test_svg = document.getElementById('test-svg');
console.log(test_div.className);
console.log(test_svg.className);
#test-div {
width: 200px;
height: 50px;
background: blue;
}
<div class="test div" id="test-div"></div>
<svg width="200" height="50" viewBox="0 0 200 50">
<rect width="200" height="50" fill="green" class="test svg" id="test-svg" />
</svg>
如果您运行此代码,您将在开发者控制台中看到类似以下内容。
test div
SVGAnimatedString { baseVal="test svg", animVal="test svg"}
如果我们SVGAnimatedString
像 jQuery 那样将该对象强制转换为字符串,我们就会有[object SVGAnimatedString]
,这就是 jQuery 失败的地方。
jQuery SVG 插件如何处理这个:
jQuery SVG 插件通过修补相关函数来添加 SVG 支持来解决这个问题。
function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
这个函数将检测一个元素是否是一个 SVG 元素,如果是,它将在返回属性之前使用对象的baseVal
属性(SVGAnimatedString
如果可用)class
。
jQuery 在这个问题上的历史立场:
jQuery 目前在他们的Won't Fix页面上列出了这个问题。这是相关部分。
SVG/VML 或命名空间元素错误
jQuery 主要是用于 HTML DOM 的库,因此与 SVG/VML 文档或命名空间元素相关的大多数问题都超出了范围。我们确实尝试解决“渗透”到 HTML 文档的问题,例如从 SVG 中冒出的事件。
显然 jQuery 考虑了 jQuery 核心范围之外的完整 SVG 支持,并且更适合插件。