所有浏览器的图像加载时的 JavaScript/jQuery 事件侦听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7442821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:17:38  来源:igfitidea点击:

JavaScript/jQuery event listener on image load for all browsers

javascriptjavascript-eventsloadjquery

提问by matteok

I am looking for a way to implement this for as many browsers as possible:

我正在寻找一种方法来为尽可能多的浏览器实现这一点:

var image = new Image();
image.addEventListener("load", function() {
                               alert("loaded");
}, false);
image.src = "image_url.jpg";

This didn't work in IE so I googled and found out that IE's lower than 9 do not support .addEventListener(). I know there is a jQuery equivalent called .bind()but that doesn't work on an Image(). What do I have to change for this to work in IE too?

这在 IE 中不起作用,所以我用谷歌搜索并发现 IE 低于 9 不支持.addEventListener(). 我知道有一个 jQuery 等价物,.bind()但它不适用于Image(). 我必须改变什么才能在 IE 中工作?

回答by Jose Faeti

IE supports attachEvent instead.

IE 支持 attachEvent。

image.attachEvent("onload", function() {
    // ...
});

With jQuery, you can just write

使用 jQuery,你可以只写

$(image).load(function() {
    // ...
});

When it comes to events, if you have the possibility of using jQuery I would suggest using it because it will take care of browser compatibility. Your code will work on all major browser and you don't have to worry about that.

当涉及到事件时,如果您有可能使用 jQuery,我建议您使用它,因为它会考虑浏览器兼容性。您的代码将适用于所有主要浏览器,您不必担心。

Note also that in order to the load event being fired in IE, you need to make sure the image won't be loaded from the cache, otherwise IE won't fire the load event.

另请注意,为了在 IE 中触发 load 事件,您需要确保不会从缓存中加载图像,否则 IE 不会触发 load 事件。

To do this, you can append a dummy variable at the end of the url of your image, like this

为此,您可以在图像的 url 末尾附加一个虚拟变量,如下所示

image.setAttribute( 'src', image.getAttribute('src') + '?v=' + Math.random() );

Some known issues using the jQuery load method are

使用 jQuery 加载方法的一些已知问题是

Caveats of the load event when used with images

A common challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:

  • It doesn't work consistently nor reliably cross-browser
  • It doesn't fire correctly in WebKit if the image src is set to the same src as before
  • It doesn't correctly bubble up the DOM tree
  • Can cease to fire for images that already live in the browser's cache

与图像一起使用时加载事件的注意事项

开发人员尝试使用 .load() 快捷方式解决的一个常见挑战是在图像(或图像集合)完全加载后执行函数。有几个已知的警告应该注意。这些是:

  • 它不能始终如一地工作,也不能可靠地跨浏览器
  • 如果图像 src 设置为与以前相同的 src,则它不会在 WebKit 中正确触发
  • 它没有正确地冒泡 DOM 树
  • 对于已经存在于浏览器缓存中的图像,可以停止触发

See the jQuery docsfor more info.

有关更多信息,请参阅jQuery 文档

回答by Alex

You have to use .attachEvent()rather than .addEventListener().

您必须使用.attachEvent()而不是.addEventListener().

if (image.addEventListener) {
  image.addEventListener('load', function() {
       /* do stuff */ 
  });
} else {
  // it's IE!
  image.attachEvent('onload', function() {
    /* do stuff */
  });
}

回答by pimvdb

new Imagebasically returns an <img>tag, so you can code in jQuery like: http://jsfiddle.net/pimvdb/LAuUR/1/.

new Image基本上返回一个<img>标签,所以你可以在 jQuery 中编码,如:http: //jsfiddle.net/pimvdb/LAuUR/1/

$("<img>", { src: '...' })
    .bind('load', function() {
        alert('yay');
    });

EDIT:in case of loading valid images

编辑:在加载有效图像的情况下

$('.buttons').html('');

var range = [];
for (var i = 1; i <=50; i++) range.push(i);

range.forEach(function(i) {
  var img_src = 'http://i.imgur.com/' + i + '.jpg';
  var $img = $("<img>", {
    src: img_src
  });

  $img.on('load', function() {
    $('.buttons').append($img);
  });

  $img.on('error', function() {
  });

});

回答by Shef

You can use attachEvent, but I would rather prefer you would add the addEventListenerlistener yourself. Here is the code on that MDN link for adding the event listener:

您可以使用attachEvent,但我宁愿您addEventListener自己添加侦听器。这是该 MDN 链接上用于添加事件侦听器的代码:

if (!Element.prototype.addEventListener) {
    var oListeners = {};
    function runListeners(oEvent) {
        if (!oEvent) { oEvent = window.event; }
        for (var iLstId = 0, iElId = 0, oEvtListeners = oListeners[oEvent.type]; iElId < oEvtListeners.aEls.length; iElId++) {
            if (oEvtListeners.aEls[iElId] === this) {
                for (iLstId; iLstId < oEvtListeners.aEvts[iElId].length; iLstId++) { oEvtListeners.aEvts[iElId][iLstId].call(this, oEvent); }
                break;
            }
        }
    }
    Element.prototype.addEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
        if (oListeners.hasOwnProperty(sEventType)) {
            var oEvtListeners = oListeners[sEventType];
            for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
                if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
            }
            if (nElIdx === -1) {
                oEvtListeners.aEls.push(this);
                oEvtListeners.aEvts.push([fListener]);
                this["on" + sEventType] = runListeners;
            } else {
                var aElListeners = oEvtListeners.aEvts[nElIdx];
                if (this["on" + sEventType] !== runListeners) {
                    aElListeners.splice(0);
                    this["on" + sEventType] = runListeners;
                }
                for (var iLstId = 0; iLstId < aElListeners.length; iLstId++) {
                    if (aElListeners[iLstId] === fListener) { return; }
                }           
                aElListeners.push(fListener);
            }
        } else {
            oListeners[sEventType] = { aEls: [this], aEvts: [ [fListener] ] };
            this["on" + sEventType] = runListeners;
        }
    };
    Element.prototype.removeEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
        if (!oListeners.hasOwnProperty(sEventType)) { return; }
        var oEvtListeners = oListeners[sEventType];
        for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
            if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
        }
        if (nElIdx === -1) { return; }
        for (var iLstId = 0, aElListeners = oEvtListeners.aEvts[nElIdx]; iLstId < aElListeners.length; iLstId++) {
            if (aElListeners[iLstId] === fListener) { aElListeners.splice(iLstId, 1); }
        }
    };
}

回答by tobek

The best way to do it now is probably to use jQuery and the jQuery plugin imagesLoadedinstead of jQuery's built-in load()or plain JS. The plugin takes care of the various browser quirks that the jQuery docs refer to, namely regarding cached images and re-firing the callback if the new image's srcis the same. Just download jquery.imagesloaded.min.js, add it in with <script src="jquery.imagesloaded.min.js"></script>and you're good to go:

现在最好的方法可能是使用 jQuery 和 jQuery 插件imagesLoaded而不是 jQuery 的内置load()或普通 JS。该插件负责处理 jQuery 文档所引用的各种浏览器怪癖,即关于缓存图像并在新图像相同时重新触发回调src。只需下载jquery.imagesloaded.min.js,添加它<script src="jquery.imagesloaded.min.js"></script>,你就可以开始了:

$(image).imagesLoaded(function() {
    alert("loaded");
});