jQuery 3没有这个问题
jQuery 3.0的修改之一是:
添加SVG类操作(#2199, 20aaed3)
解决此问题的一种方法是升级到jQuery 3。它非常好用:
var flip = true;
setInterval(function() {
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元素一起使用的原因是因为jQuery 3.0之前的版本在这些函数中使用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"}
如果我们像jQuery一样将SVGAnimatedString对象转换为字符串,我们会得到[object SVGAnimatedString],这就是jQuery失败的地方。
jQuery SVG插件如何处理这个问题:
jQuery SVG插件通过修补相关函数来添加SVG支持来解决这个问题。
摘自jQuery SVG
jquery.svgdom.js
:
function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
这个函数将检测一个元素是否为SVG元素,如果是,则会使用SVGAnimatedString
对象的baseVal
属性(如果可用),然后退回到class
属性。
jQuery在这个问题上的历史立场:
目前,jQuery在其Won't Fix页面上列出了这个问题。以下是相关部分。
SVG/VML或命名空间元素错误
jQuery主要是用于HTML DOM的库,因此大多数与SVG/VML文档或命名空间元素相关的问题都不在范围内。 但是,我们确实尝试解决“渗透”到HTML文档中的问题,例如从SVG冒泡出来的事件。
显然,jQuery认为完整的SVG支持超出了jQuery核心的范围,并且更适合插件。