仅在未被任何处理程序阻止的情况下触发事件?

时间:2016-10-14 15:10:36

标签: javascript jquery

我目前有一个JavaScript组件,它使用JQuery触发DOM事件,如下所示:

$(document).trigger('myevent', mydata);

其他组件注册事件处理程序并在接收事件时相应地更新自己。

现在,我希望以这样的方式扩展此功能,任何已注册的组件都应该有机会阻止这些更新(即拒绝该事件)。

我想过要有两个事件:

$(document).trigger('myevent-before', mydata);
if( ??? )
    $(document).trigger('myevent', mydata);

喜欢拒绝更新的组件会注册myevent-before并返回某种信息,以防止触发方触发实际的myevent。< / p>

这是要走的路吗?

  • 如果是,如何制定if条款?如果任何被调用的事件处理程序返回false,trigger()会返回一些指示符吗?
  • 如果不是,用JavaScript做这样的事情的方法是什么?

示例1:

  1. 主要组成部分:嘿,有没有人对即将推出的更新有疑问?
  2. 组件A:否。
  3. 组件B:否。
  4. 主要组件:好的,然后我会触发实际的更新!
  5. 示例2:

    1. 主要组成部分:嘿,有没有人对即将推出的更新有疑问?
    2. 组件A:否。
    3. 组件B:是的。
    4. 主要组成部分:哦,好的,没有更新。
    5. (请注意,当然注册的组件可能超过2个)

3 个答案:

答案 0 :(得分:1)

可以使用普通的Javascript执行此操作。 不确定jQuery是否也可以。

&#13;
&#13;
var input = document.getElementById( 'input' );
var makered = document.getElementById( 'makered' );

makered.addEventListener( 'click', function( e ) {
  var beforeMakeRedEvent = new Event( 'before-make-red', { cancelable: true } );
  input.dispatchEvent( beforeMakeRedEvent );
  if( beforeMakeRedEvent.defaultPrevented ) {
    console.log( 'Sorry, unable to make it red!' );
  }
  else {
    console.log( 'Making it red! Yeeehaawww!' );
  }
} );

input.addEventListener( 'before-make-red', function( e) {
  if( this.value == 1 ) {
    e.preventDefault();  
  }
} );
&#13;
<input id="input" value="5">
<button id="makered">Make red</button>
&#13;
&#13;
&#13;

以上示例转换为jQuery:

&#13;
&#13;
$( '#makered' ).on( 'click', function( e ) {
  var beforeMakeRedEvent = jQuery.Event( 'before-make-red' );
  $( '#input' ).trigger( beforeMakeRedEvent );
  if( beforeMakeRedEvent.isDefaultPrevented() ) {
    console.log( 'Sorry, unable to make it red!' );
  }
  else {
    console.log( 'Making it red! Yeeehaawww!' );
  }
} );

$( '#input' ).on( 'before-make-red', function( e ) {
  if( this.value == 1 ) {
    e.preventDefault();
  }
} );
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input id="input" value="5">
<button id="makered">Make red</button>
&#13;
&#13;
&#13;

让我们说,为了论证,你想要传递有关为什么某个组件想要阻止事件的默认操作的信息。然后你就可以像这样实现它。无论哪个组件首先服务,都会立即阻止事件的进一步传播,阻止其他处理程序覆盖其他信息(我可以想到一个更强大的系统,但这只是可能性的一个例子):

&#13;
&#13;
/* main.js */
$( '#makered' ).on( 'click', function( e ) {
  var beforeMakeRedEvent = jQuery.Event( 'before-make-red' );
  $( '#input' ).trigger( beforeMakeRedEvent );
  if( beforeMakeRedEvent.isDefaultPrevented() ) {
    // include the reason it was prevented
    console.log( 'Sorry, unable to make it red!', beforeMakeRedEvent.preventReason );
  }
  else {
    console.log( 'Making it red! Yeeehaawww!' );
  }
} );

/* component1.js */
$( '#input' ).on( 'before-make-red', function( e ) {
  if( this.value == 1 ) {
    e.preventDefault();
    
    // this is just a custom ad hoc property
    e.preventReason = 'I don\'t like the number 1!';
    
    // If I prevented it first, stop further propagation
    // to prevent others from fiddling with the event
    
    // try to leave this out, to see what happens
    e.stopImmediatePropagation();
  }
} );

/* component2.js */
$( '#input' ).on( 'before-make-red', function( e ) {
  if( this.value == 1 ) {
    e.preventDefault();
    
    // this is just a custom ad hoc property
    e.preventReason = 'I don\'t like the number 1 either!';
    
    // If I prevented it first, stop further propagation
    // to prevent others from fiddling with the event
    
    // leaving this out won't do much in this example
    e.stopImmediatePropagation();
  }
} );
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="input" value="5">
<button id="makered">Make red</button>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我认为这个问题应该被颠倒描述:组件A和组件B可能告诉主组件他们关于更新的特定状态是什么(如果可以进行更新,则为true,否则为false)。这可以通过Main组件公开的事件或方法来控制,以保持它们各自的状态,组件A和B可以调用这些方法,当它们落入特定条件时(阻止它们更新),将它们的特定状态设置为false。并在此阻止条件结束后将该状态重置为true。

因此,当一个新的更新周期从Main组件开始时,它要做的第一件事是迭代状态数组以检查某些组件状态是否设置为false。如果是这种情况,则更新停止。如果所有组件状态都设置为true,则继续更新。

答案 2 :(得分:0)

更新2:使用基于JQuery的@DecentDabbler解决方案,这更加惯用。

更新1:.trigger()是同步的,不需要.when()。一个简短的方法是:

// main.js:
var maySend = true;
var prevent = function() { maySend = false; };
$(document).trigger('myevent-before', [prevent]);
if(maySend) {
    $(document).trigger('myevent');
}

// component.js:
$(document).on('myevent-before', function(e, prevent) {
    if(some_condition) {
        prevent();
    }
});

使用.when()的旧解决方案:

在网上搜索了好几个小时后,我发现了solution基于JQuery的.when()方法:

// main.js:
var maySend = true;
var prevent = function() { maySend = false; };
$.when($(document).trigger('myevent-before', [prevent])).done(function(){
    if(maySend) {
        $(document).trigger('myevent');
    }
});

// component.js:
$(document).on('myevent-before', function(e, prevent) {
    if(some_condition) {
        prevent();
    }
});