【问题标题】:Is there a way to make SVG className backward compatible?有没有办法使 SVG className 向后兼容?
【发布时间】:2020-11-21 03:14:03
【问题描述】:

许多旧库依赖 className 来识别它们的上下文。

所以点击处理程序可以如下所示:

function click(event)
{
   if (event.target.className.indexOf('something')!= -1){
       // Do something
   }
}

但是如果目标元素是 svg 元素,这将失败。 原因是svg className是SVGAnimatedString类型的对象

是否有任何临时解决方法可以避免旧代码出现问题? 更改处理程序不是一种选择,因为不清楚有多少库具有此代码,并且更改库代码可能是不可能的。

将 SVG 更改为其他元素不是一种选择,因为 SVG 是第 3 方控件的一部分。

更新:

“是否有任何临时解决方法可以避免旧代码出现问题?” 根据 cmets 似乎不清楚。我的目标是查看是否有任何 polyfill 或任何其他技术可用于临时使 SVG 元素将其 className 作为字符串,直到第 3 方库赶上。然后我将更新 3rd 方库并还原此代码。

到目前为止 - 简单地覆盖 className 似乎是不可能的,因为它似乎只有 getter 而没有用于 SVG 元素的 setter。

function oldModuleHandler(e) {
  if (e.className.indexOf("initial") > -1 || e.className.indexOf("fixed") > -1) {
    alert('Behaves as expected.');
  }
}

function theFix(e) {
  e.className = "fixed";
}
<html>

<head>

</head>

<body>

  <div style="border:2px solid silver;">
    <h2>Demo:</h2>
    Click on the left square, it is a div and it will have it's color changed to green because .className.indexOf will go through just fine. Same does not apply for SVG.<br/> <br/><br/>
    <div onclick="theFix(this); oldModuleHandler(this)" class="initial">
    </div>

    <svg class="initial" onclick="theFix(this); oldModuleHandler(this)"></svg>
    <div style="clear:both;"></div>
  </div>
  <style>
    .fixed {
      background: green !important;
      width: 80px;
      height: 80px;
      float: left;
    }
    
    .initial {
      background: transparent;
      border: 1px solid black;
      width: 80px;
      height: 80px;
      float: left;
    }
  </style>
</body>

</html>

更新 2 我添加了一个小代码来演示这个问题。如果你点击左边的方块(它是一个 div)——它会工作得很好。如果你点击右边的方块 - SVG - 它不会起作用,因为 .className.indexOf() 会抛出一个错误。

【问题讨论】:

  • 您的要求似乎已经足够严格,以确保没有解决方案是可能的。
  • 谢谢,@RobertLongson,实际上 - 我正在寻找一些我可以使用的聪明的 hack 或解决方法,以便让第 3 方库有时间赶上。我假设现在依赖 event.target.className 是一个字符串是一个错误,在我们有一个有效的(根据规范)情况下这是不正确的。所以我的目标是在我这边解决它,直到第 3 方供应商修复他们的代码、更新库、恢复“解决方法”。
  • SVG 已经存在 20 年了。如果图书馆有任何支持它的意图,他们现在就会有。如果您使用的是 SVG,请转到更好的库。
  • 至于你最后的观察,这是错误的。 SVG 中有一个用于 className 的设置器。
  • 我认为你适合二传手。我添加了一个小例子。然后 - 我还发现这里的 W3C 规范:w3.org/TR/2015/WD-SVG2-20150709/types.html#InterfaceSVGElement 说 className 可能在某些时候被弃用。不知道该怎么想或如何行动。我将不得不研究从 SVG 切换是否可以成为一种解决方案。

标签: javascript svg polyfills vuesax


【解决方案1】:

您可以使用 getAttributesetAttribute 或 'classList 方法:

function oldModuleHandler(e) {
  var c = e.getAttribute('class');
  if (~c.indexOf("initial") || ~c.indexOf("fixed")) {
    alert('Behaves as expected.');
  }
}

function theFix(e) {
  e.className = "fixed";
  e.setAttribute('class', 'fixed')
  // OR 
  e.classList.add('fixed')
}
.fixed {
      background: green !important;
      width: 80px;
      height: 80px;
      float: left;
    }
    
    .initial {
      background: transparent;
      border: 1px solid black;
      width: 80px;
      height: 80px;
      float: left;
    }
<div style="border:2px solid silver;">
    <h2>Demo:</h2>
    Click on the left square, it is a div and it will have it's color changed to green because .className.indexOf will go through just fine. Same does not apply for SVG.<br/> <br/><br/>
    <div onclick="theFix(this); oldModuleHandler(this)" class="initial">
    </div>

    <svg class="initial" onclick="theFix(this); oldModuleHandler(this)"></svg>
    <div style="clear:both;"></div>
  </div>

和/或查看Proxy API

【讨论】:

  • 非常感谢!看起来很有希望。我会尽快对其进行测试并返回一些结果。
猜你喜欢
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 2013-10-16
  • 1970-01-01
  • 2020-08-30
相关资源
最近更新 更多