JavaScript 中有没有一种方法可以在浏览器在解析 HTML 时加载它们之前更改图像路径?

Is there a way in JavaScript to change image path before the browser loads them when parsing HTML?

我正在使用 IE Edge 的模拟器模式来测试一些工作,我从事的项目之一需要 IE8。模拟器对于调试一些原始 IE8 在黑盒方面做得很好的东西非常有用。我正在尝试找到解决方法 this bug,因为 Microsoft 不愿意修复它。

问题是 IE8 模拟器在加载 SVG 图像时挂起。我目前正在使用 this SVG fallback library,它在真正的 IE8 上效果很好,但我想知道是否有办法修改 eventsobject prototypes 在解析 HTML 时使用 Javascript 更改浏览器在尝试加载 SVG 图像之前的行为?有没有办法解决这个问题,还是我应该忍受这个错误?我有这个肮脏的解决方法可以解决问题,但我希望找到更主动的解决方案。

var fixMySVG = setInterval(function () {
    var elements = document.getElementsByTagName('img');
    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];
        element.src = element.src.replace(/^(.+)(\.svg)(\?.)*$/ig, '.' + 'png' + '');
    }
    if (document.readyState == 'complete') {
        clearInterval(fixMySVG);
    }
}, 100);

没有错误,图像只是停留在'uninitialized'状态(所以我无法使用onerror事件)。我也不知道我可以使用任何 onbeforeoload 事件。

使用间隔是唯一的解决方案吗?

编辑

我意识到没有完美的解决方案,但要解决基本的 <img>backgroundImage 样式,使用 interval 似乎可以很好地完成工作而不会影响性能。最重要的是,回退图像似乎加载得更快。我更新了我的 SVG 回退以使用间隔而不是使用解决 IE8 模拟器和真实 IE8 的 onload 事件。

这是一个非常奇怪的错误,因为在 Edge 中没有 older-version 模拟模式,只有移动模式和 user-agent 字符串模拟,它只允许您 "to debug errors caused by browser sniffing",但是在绝不可能与某些功能有关 non-support。

使用后备是众多选项之一,但没有 "clean" 方法可以做到这一点。最重要的是,它不会使用 <object><iframe><embded> 元素解析 SVG 图像,也不会内联 <svg> 元素。

所以这并不直接指向您的问题,应该由 IE 团队修复,因为这是他们浏览器中的错误,但只是为了解决问题,这里是在开始获取原始图像之前更改图像 src 的方法。

免责声明

再说一次,这是一个 hack,不应在任何生产或开发站点中使用 可能仅用于像您这样的边缘调试案例和实验但仅此而已!

注意:这将适用于现代浏览器,包括带有 IE8 user-string 仿真集的 Edge,但不适用于原始 IE8。


转储前

此代码应在文档的 <head> 中调用,最好在 top-most 中调用,因为在它之前调用的所有内容都会被调用两次。

阅读评论。

<script id="replaceSrcBeforeLoading">
  // We need to set an id to the script tag
  // This way we can avoid executing it in a loop
  (function replaceSrcBeforeLoading(oldSrc, newSrc) {
    // first stop the loading of the document
    if ('stop' in window) window.stop();
    // IE didn't implemented window.stop();
    else if ('execCommand' in document) document.execCommand("Stop");
    // clear the document
    document.removeChild(document.documentElement);

    // the function to rewrite our actual page from the xhr response
    var parseResp = function(resp) {
      // create a new HTML doc
      var doc = document.implementation.createHTMLDocument(document.title);
      // set its innerHTML to the response
      doc.documentElement.innerHTML = resp;
      // search for the image you want to modify
      // you may need to tweak it to search for multiple images, or even other elements
      var img = doc.documentElement.querySelector('img[src*="' + oldSrc + '"]');
      // change its src
      img.src = newSrc;
      // remove this script so it's not executed in a loop
      var thisScript = doc.getElementById('replaceSrcBeforeLoading');
      thisScript.parentNode.removeChild(thisScript);
      // clone the fetched document
      var clone = doc.documentElement.cloneNode(true);
      // append it to the original one
      document.appendChild(clone);
      // search for all script elements
      // we need to create new script element in order to get them executed
      var scripts = Array.prototype.slice.call(clone.querySelectorAll('script'));

      for (var i = 0; i < scripts.length; i++) {
        var old = scripts[i];
        var script = document.createElement('script');
        if (old.src) {
          script.src = old.src;
        }
        if (old.innerHTML) {
          script.innerHTML = old.innerHTML;
        }
        old.parentNode.replaceChild(script, old);
      }
    }

    // the request to fetch our current doc
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && (this.status == 200 || this.status == 0)) {
        var resp = this.responseText || this.response;
        parseResp(resp);
      }
    };
    xhr.open('GET', location.href);
    xhr.send();
  })('oldSrc.svg',
    'newSrc.svg');
</script>

还有一个 live example 不能与 IE8 UA 字符串一起使用,因为 plnkr.co 不允许在他的网站上使用此浏览器:-/