最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does returning false stop propagation with jQuery while it doesn't with POJS? - Stack Overflow

programmeradmin3浏览0评论

Here is a jsfiddle using POJS showing that return false; doesn't stop the event's propagation: /

Here is another using jQuery showing that return false; does stop the event's propagation: /

Edit: The one explaining to me why jQuery does this - differing from the original behavior intentionally - (and where in the code) gets the answer.

Here is the code (long, but very easy to read):

  • HTML for both versions:

    <div id="parent1">
        <div id="child1"><a href="#" id="a1">child1</a></div>
    </div>
    
    <div id="parent2">
        <div id="child2"><a href="#" id="a2">child2</a></div>
    </div>
    
    <div id="parent3">
        <div id="child3"><a href="#" id="a3">child3</a></div>
    </div>
    
  • POJS:

    document.getElementById( 'child1' ).onclick = function( e ) {
        console.log( 'child1' );
        e.preventDefault();
    };
    
    document.getElementById( 'parent1' ).onclick = function( e ) {
        console.log( 'parent1' );
    };
    
    document.getElementById( 'child2' ).onclick = function( e ) {
        console.log( 'child2' );
        return false;
    };
    
    document.getElementById( 'parent2' ).onclick = function( e ) {
        console.log( 'parent2' );
    };
    
    document.getElementById( 'child3' ).onclick = function( e ) {
        console.log( 'child3' );
        e.stopPropagation();
    };
    
    document.getElementById( 'parent3' ).onclick = function( e ) {
        console.log( 'parent3' );
    };
    
  • jQuery version:

    $( '#child1' ).click( function( e ) {
        console.log( 'child1' );
        e.preventDefault();
    });
    
    $( '#parent1' ).click( function( e ) {
        console.log( 'parent1' );
    });
    
    $( '#child2' ).click( function( e ) {
        console.log( 'child2' );
        return false;
    });
    
    $( '#parent2' ).click( function( e ) {
        console.log( 'parent2' );
    });
    
    $( '#child3' ).click( function( e ) {
        console.log( 'child3' );
        e.stopPropagation();
    });
    
    $( '#parent3' ).click( function( e ) {
        console.log( 'parent3' );
    });
    

Here is a jsfiddle using POJS showing that return false; doesn't stop the event's propagation: http://jsfiddle/Ralt/Lz2Pw/

Here is another using jQuery showing that return false; does stop the event's propagation: http://jsfiddle/Ralt/D5Mtg/

Edit: The one explaining to me why jQuery does this - differing from the original behavior intentionally - (and where in the code) gets the answer.

Here is the code (long, but very easy to read):

  • HTML for both versions:

    <div id="parent1">
        <div id="child1"><a href="#" id="a1">child1</a></div>
    </div>
    
    <div id="parent2">
        <div id="child2"><a href="#" id="a2">child2</a></div>
    </div>
    
    <div id="parent3">
        <div id="child3"><a href="#" id="a3">child3</a></div>
    </div>
    
  • POJS:

    document.getElementById( 'child1' ).onclick = function( e ) {
        console.log( 'child1' );
        e.preventDefault();
    };
    
    document.getElementById( 'parent1' ).onclick = function( e ) {
        console.log( 'parent1' );
    };
    
    document.getElementById( 'child2' ).onclick = function( e ) {
        console.log( 'child2' );
        return false;
    };
    
    document.getElementById( 'parent2' ).onclick = function( e ) {
        console.log( 'parent2' );
    };
    
    document.getElementById( 'child3' ).onclick = function( e ) {
        console.log( 'child3' );
        e.stopPropagation();
    };
    
    document.getElementById( 'parent3' ).onclick = function( e ) {
        console.log( 'parent3' );
    };
    
  • jQuery version:

    $( '#child1' ).click( function( e ) {
        console.log( 'child1' );
        e.preventDefault();
    });
    
    $( '#parent1' ).click( function( e ) {
        console.log( 'parent1' );
    });
    
    $( '#child2' ).click( function( e ) {
        console.log( 'child2' );
        return false;
    });
    
    $( '#parent2' ).click( function( e ) {
        console.log( 'parent2' );
    });
    
    $( '#child3' ).click( function( e ) {
        console.log( 'child3' );
        e.stopPropagation();
    });
    
    $( '#parent3' ).click( function( e ) {
        console.log( 'parent3' );
    });
    
Share Improve this question edited Jun 29, 2012 at 7:11 ThinkingStiff 65.4k30 gold badges147 silver badges241 bronze badges asked May 4, 2012 at 15:45 Florian MargaineFlorian Margaine 60.9k15 gold badges93 silver badges120 bronze badges 8
  • I wonder if the return false is being picked up by jQuery's event handling and stops the propagation there... – Ben Everard Commented May 4, 2012 at 15:52
  • If that is so, I'd like to see where :-) Also, why would it be doing this? – Florian Margaine Commented May 4, 2012 at 15:52
  • Ah, this might be it. Go to the jQuery source (code.jquery./jquery-1.7.2.js), search for 'event.stopPropagation', this happens just after a condition checking if a returned value is false. – Ben Everard Commented May 4, 2012 at 15:55
  • Strange that e.stopPropagation() is the only method that works for your POJS example. – Rory McCrossan Commented May 4, 2012 at 15:58
  • 1 And from the documentation (second to last paragraph under The event handler and its environment): "Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault()." – Anthony Grist Commented May 4, 2012 at 15:58
 |  Show 3 more ments

1 Answer 1

Reset to default 8

On line 3331 of version 1.7.1, in jQuery.event.dispatch:

ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
         .apply( matched.elem, args );

if ( ret !== undefined ) {
    event.result = ret;
    if ( ret === false ) {
        event.preventDefault();
        event.stopPropagation();
    }
}

A lot of packaging has happened before this line, but basically, it runs the handler function (either a raw function, or the handler memeber function of a handlerObject) using apply. If the result of that call is false, it does preventDefault and stopPropagation.

This is mentioned in the documentation for on():

Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault().

As for why they did it? I don't know, as I'm not not the jQuery design team, but I assume it's just because return false is a lot quicker to type than event.preventDefault(); event.stopPropagation();. (And if jQuery isn't about making sure you have less to type, I'm not sure what it's about.)

I don't believe the return value of an event handler is ever actually used anywhere in POJS (someone correct if that's wrong!). Thus, jQuery can safely have a return statement cause side effects in a handler (since returning false in a POJS handler is meaningless, no POJS functionality is harmed).

发布评论

评论列表(0)

  1. 暂无评论