Difference between jQuery.one() and jQuery.on()

前端 未结 3 686
滥情空心
滥情空心 2020-12-20 12:18

I have multiple images on my page. To detect broken images , I used this found on SO.

$(\'.imgRot\').one(\'error\',function(){
    $(this).attr(\'src\',\'bro         


        
相关标签:
3条回答
  • 2020-12-20 12:42

    jQuery will reuse the "on" method for the "one". Following is the internal code of jQuery where they'll be passing hardcoded value "1" to the function of jQuery.on() They'll turn off the triggered event further on the element using jQuery.off()

        on:function( types, selector, data, fn, one ) {
    
        if ( one === 1 ) {
              origFn = fn;
              fn = function( event ) {
                jQuery().off( event );
                return origFn.apply( this, arguments );
              };
    
        }
        off:function(types, selector, data, fn){
          on(types, selector, data, fn, 1);
        }
    

    So, in your case "error" is the event type triggered on the first image and when the jQuery.one() method called this event got turned off and then its not triggered for further on the $('.imgRot') elements

    0 讨论(0)
  • 2020-12-20 12:55

    If you look at the source code for .one() in jQuery 1.7, it just calls .on() internally except that after the event fires, it removes the event handler. So, there should be no difference in your case because error is an event that should only happen once per object anyway.

    So, there must be something else going on in your code like maybe the image objects haven't been loaded into the DOM yet when you run this code or something like that.

    If you were trying to use delegated event handling to do this (which your example does not show), then you may run into issues where the 'error' event doesn't propagate.

    It may also be that your code has timing issues due to caching. Trying to install these types of error handlers on images that are already in the DOM is a race condition. You're trying to get the error handler installed before it gets called, but the image has already started loading and the event might have already fired before you get the event handler installed. Subsequent page loads (after the first) may have cached other page elements or DNS references so it may get to the error handler quicker and perhaps even before your JS can run and install the error handlers.

    I know this is an issue with browser caching and the onload event. You can only reliably get the onload event if you attach the event handler either in the embedded HTML (so it's there when the <img> tag is first parsed or if you attach it before the .src property has been set (if creating the image programmatically). That would suggest that you can't reliably set error handlers the way you are doing for images that are in the page HTML.

    My suggestion would be this:

    • Don't try to install error handlers like this after the images are in the DOM.
    • If you assign them on programmatically generating images, then assign the event handlers before .src is assigned.
    • If you need these on images in the page's HTML, then you will have to put the event handlers in the HTML with something like <img src="xxx" onerror="yourErrorFunc(this)"> because that's the only way to guarantee that the handlers are installed before the event can occur.
    0 讨论(0)
  • 2020-12-20 13:00

    Community wiki: This generic answer does not contribute to the question OP posted but relative to the title.

    The concept of one() and on() can be explained with the below code.

    one() function is automatically moved to off state after first instance of occurance.

    on() is identical to one() but it needs to be manually put to off state otherwise the number of instances has no limit.

    var i = 1;
    $('.one').one('click', function() {
    
      $(this).text('I am clickable only once: ' + i);
      i++;
    });
    
    var j = 1;
    $('.multiple').on('click', function() {
    
      $(this).text('I was clicked ' + j + ' times');
      j++;
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="one">Click me</div>
    <div class="multiple">Click me</div>

    0 讨论(0)
提交回复
热议问题