我目前有一个JavaScript组件,它使用JQuery触发DOM事件,如下所示:
$(document).trigger('myevent', mydata);
其他组件注册事件处理程序并在接收事件时相应地更新自己。
现在,我希望以这样的方式扩展此功能,任何已注册的组件都应该有机会阻止这些更新(即拒绝该事件)。
我想过要有两个事件:
$(document).trigger('myevent-before', mydata);
if( ??? )
$(document).trigger('myevent', mydata);
喜欢拒绝更新的组件会注册myevent-before
并返回某种信息,以防止触发方触发实际的myevent
。< / p>
这是要走的路吗?
trigger()
会返回一些指示符吗?示例1:
示例2:
(请注意,当然注册的组件可能超过2个)
答案 0 :(得分:1)
可以使用普通的Javascript执行此操作。 不确定jQuery是否也可以。
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;
以上示例转换为jQuery:
$( '#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;
让我们说,为了论证,你想要传递有关为什么某个组件想要阻止事件的默认操作的信息。然后你就可以像这样实现它。无论哪个组件首先服务,都会立即阻止事件的进一步传播,阻止其他处理程序覆盖其他信息(我可以想到一个更强大的系统,但这只是可能性的一个例子):
/* 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;
答案 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();
}
});