摘要使用jquery.blockUI似乎隐藏/吞下/屏蔽按钮单击事件。
技术阶层
- Backbone 和 puppet
- backbone.radio
1.底缐
1.查询 - jquery.blockUI
(all最新版本)
应用程序
该应用程序由一个文本输入和一个按钮组成。
在 Backbone /牵线 puppet 术语方面,
1.具有2个区域的俯视图
1.作为文本输入的容器视图
1.页脚视图,其中包含按钮
1.容器视图由模型支持。
1.页脚有一个按钮,单击该按钮将发送一个backbone.radio事件。
1.在俯视图中拾取该事件。
当用户离开文本输入时,调用API(服务器/后端)。在示例中,Promise / setTimeout用于模拟调用。
在本示例中,按钮调用console.log。
代码
下面是JSFiddle Example on JSFiddle及其下面的Javascript代码
// ------------------------------------------------------------------
var Model = Backbone.Model.extend({
defaults: {
"SearchCriteria": {
"Min": { "value": "abc123", "ReadOnly": true }
}
},
async callBackend() {
//$.blockUI(); //<----- uncomment this and the button click is swallowed
await new Promise(resolve => setTimeout(resolve, 3000));
$.unblockUI();
}
});
// ------------------------------------------------------------------
// ------------------------------------------------------------------
var ContainerView = Marionette.View.extend({
template: _.template('<div><label>Container</label></div><div><input id = "min" name = "min" type = "text"/></div>'),
events: {
'change': 'onChangeData',
},
async onChangeData(data) {
console.log('start onChangeData');
await this.model.callBackend();
this.render();
console.log('end onChangeData');
}
});
// ------------------------------------------------------------------
// ------------------------------------------------------------------
var FooterView = Marionette.View.extend({
template: _.template('<div><button class="btn-footer-test">Footer</button></div>'),
events: {
"click .btn-footer-test": () => {
console.log('click test ...');
Backbone.Radio.channel("maske").trigger("select:test");
}
},
});
// ------------------------------------------------------------------
// ------------------------------------------------------------------
var TopView = Marionette.View.extend({
template: _.template("<div id='container'></div><div id='footer'></div>"),
regions: {
container: '#container',
footer: '#footer'
},
events: {
'change': 'onChangeData',
},
initialize() {
this.listenTo(Backbone.Radio.channel("maske"), "select:test", this.onTest, this);
},
onRender() {
this.showChildView('container', new ContainerView({
model: new Model()
}));
this.showChildView('footer', new FooterView());
},
onChangeData(data) {
},
onTest() {
//NOT called if jquery.blockUI present******
console.log('onTest');
}
});
// ------------------------------------------------------------------
$(document).ready(function () {
console.log('Start');
const topView = new TopView();
topView.render();
$('body').append(topView.$el);
});
使用
用户像这样使用应用程序。用户
1.更改文本输入
1.并直接单击按钮(无需先跳出字段!)
预期行为
1.对文本输入的改变触发改变事件。
- jquery.blockUI
1.异步呼叫 - jquery解除封锁UI
1.执行对该按钮的点击事件
实际行为
当jquery.blockUI函数存在时,按钮的click事件不会被执行。注解jquery.blockUI时,按钮的click事件发生,但是在await返回之前。
问题
1.我做错了什么?
1.为什么click事件会被吞掉?
1条答案
按热度按时间ljsrvy3e1#
我做错了什么?
你的期望是错误的。JavaScript中没有隐式的机制来序列化一个接一个完成的异步事件。你(开发人员)要负责异步事件的同步。
为什么click事件会被吞掉?
Click
事件触发when a mousedown and mouseup event occur on the same element。但这不是您的情况。事件的顺序如下:1.在
<button>
上的mousedown
1.在
<input>
上的change
;导致通过blockUI
显示覆盖<div>
1.覆盖
<div>
上的mouseup
1.触发
mousedown
和mouseup
的元素的最近公共父元素上的click
,即<body>
从技术上讲,在输入改变后点击按钮似乎是不可能的,因为覆盖层显示在
mouseup
之前,但是有一种方法。如果你在覆盖层显示时点击并按住鼠标按钮,然后释放,click
事件将在按钮上触发,但这不是你想要的。尝试使用这个代码片段。它记录每个
mousedown
、mouseup
、click
和change
事件。它在<input>
上注册异步change
事件处理程序,第一秒不做任何事情,然后显示一个覆盖图,然后休眠3秒钟,最后隐藏覆盖。你可以根据你保持鼠标按下按钮的时间来观察各种行为。更改输入文本并快速单击按钮
button.mousedown
input.change
button.mouseup
button.click
更改输入文本,单击按钮并按住1秒钟,然后松开
button.mousedown
input.change
鼠标上移分隔符
正文.单击
更改输入文本,单击按钮并按住4秒钟(直到覆盖消失),然后松开
button.mousedown
input.change
button.mouseup
button.click
第一个
您将很难解决这个问题,因为在正常情况下,不会在按钮上触发
click
事件,因此我建议您重新考虑您的用户界面。当您使用async/promises时,为什么还要阻塞用户界面?它是为了避免阻塞而发明的。