backbone.js 为什么jquery.blockUI会吞掉onClick事件?

3zwjbxry  于 2022-11-10  发布在  jQuery
关注(0)|答案(1)|浏览(141)

摘要使用jquery.blockUI似乎隐藏/吞下/屏蔽按钮单击事件。
技术阶层

  1. Backbone 和 puppet
  2. backbone.radio
    1.底缐
    1.查询
  3. 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.对文本输入的改变触发改变事件。

  1. jquery.blockUI
    1.异步呼叫
  2. jquery解除封锁UI
    1.执行对该按钮的点击事件

实际行为

当jquery.blockUI函数存在时,按钮的click事件不会被执行。注解jquery.blockUI时,按钮的click事件发生,但是在await返回之前。

问题

1.我做错了什么?
1.为什么click事件会被吞掉?

ljsrvy3e

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.触发mousedownmouseup的元素的最近公共父元素上的click,即<body>
从技术上讲,在输入改变后点击按钮似乎是不可能的,因为覆盖层显示在mouseup之前,但是有一种方法。如果你在覆盖层显示时点击并按住鼠标按钮,然后释放,click事件将在按钮上触发,但这不是你想要的。
尝试使用这个代码片段。它记录每个mousedownmouseupclickchange事件。它在<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时,为什么还要阻塞用户界面?它是为了避免阻塞而发明的。

相关问题