Javascript 为什么jquery.blockUI会吞下onClick事件?

Javascript 为什么jquery.blockUI会吞下onClick事件?,javascript,backbone.js,marionette,jquery-blockui,Javascript,Backbone.js,Marionette,Jquery Blockui,摘要使用jquery.blockUI似乎隐藏了/吞咽/屏蔽按钮单击事件 技术Stach 脊梁木偶 主干网广播 强调 jquery jquery.blockUI (全部为最新版本) 应用程序 该应用程序由一个文本输入和一个按钮组成 就主干网/木偶网术语而言,有 具有两个区域的俯视图 作为文本输入的容器视图 包含按钮的页脚视图 容器视图由模型支持 页脚有一个按钮,单击该按钮将发送backbone.radio事件 此事件将在俯视图中拾取 当用户离开文本输入时,将调用API(服务器/后端)。在本例

摘要使用jquery.blockUI似乎隐藏了/吞咽/屏蔽按钮单击事件

技术Stach

  • 脊梁木偶
  • 主干网广播
  • 强调
  • jquery
  • jquery.blockUI
  • (全部为最新版本)


    应用程序

    该应用程序由一个文本输入和一个按钮组成

    就主干网/木偶网术语而言,有

  • 具有两个区域的俯视图
  • 作为文本输入的容器视图
  • 包含按钮的页脚视图
  • 容器视图由模型支持
  • 页脚有一个按钮,单击该按钮将发送backbone.radio事件
  • 此事件将在俯视图中拾取
  • 当用户离开文本输入时,将调用API(服务器/后端)。在本例中,Promise/setTimeout用于模拟调用

    在本例中,该按钮调用console.log


    代码

    下面是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);
    });
    
    //------------------------------------------------------------------
    var Model=Backbone.Model.extend({
    默认值:{
    “搜索标准”:{
    “Min”:{“value”:“abc123”,“ReadOnly”:true}
    }
    },
    异步callBackend(){
    //$.blockUI();//设置超时(解析,3000));
    $.unbui();
    }
    });
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    var ContainerView=marionete.View.extend({
    模板:u.template('Container'),
    活动:{
    “更改”:“onChangeData”,
    },
    异步onChangeData(数据){
    log('start onChangeData');
    等待这个.model.callBackend();
    这个。render();
    log('end onChangeData');
    }
    });
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    var FooterView=marionete.View.extend({
    模板:u.template('Footer'),
    活动:{
    “单击.btn页脚测试”:()=>{
    log('click test…');
    主干。无线电。频道(“屏蔽”)。触发器(“选择:测试”);
    }
    },
    });
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    var TopView=木偶网.View.extend({
    模板:u.template(“”),
    区域:{
    容器:“#容器”,
    页脚:“#页脚”
    },
    活动:{
    “更改”:“onChangeData”,
    },
    初始化(){
    this.listenTo(Backbone.Radio.channel(“maske”),“select:test”,this.onTest,this);
    },
    onRender(){
    this.showChildView('container',newcontainerView({
    型号:新型号()
    }));
    this.showChildView('footer',newfooterView());
    },
    onChangeData(数据){
    },
    onTest(){
    //如果jquery.blockUI存在,则不调用******
    console.log('onTest');
    }
    });
    // ------------------------------------------------------------------
    $(文档).ready(函数(){
    console.log('Start');
    const topView=新topView();
    render();
    $('body').append(topView.$el);
    });
    

    使用

    用户像这样使用应用程序。用户

  • 更改文本输入
  • 并直接单击按钮(不首先将选项卡移出字段!)

  • 预期行为

  • 对文本输入的更改将触发更改事件。
  • jquery.blockUI
  • 异步调用
  • jqueryunbui
  • 执行按钮的单击事件

  • 实际行为

    当jquery.blockUI函数存在时,不会执行按钮的单击事件。注释jquery.blockUI时,按钮单击事件会在等待返回之前发生


    问题

  • 我做错了什么
  • 为什么点击事件会被吞没
  • 我做错了什么

    你的期望是错误的。JavaScript中没有一种隐式机制可以一个接一个地序列化异步事件。您(开发人员)负责异步事件的同步

    为什么点击事件会被吞没

    单击事件激发。这不是你的情况。事件顺序如下:

  • 上更改
    ;通过
    blockUI
  • 覆盖层上的鼠标悬停
  • 单击触发
    mousedown
    mouseup
    的元素的最近公共父元素,即
  • 从技术上讲,在输入更改后,似乎不可能单击按钮,因为覆盖显示在
    mouseup
    之前,但是有一种方法。如果在显示覆盖时单击并按住鼠标按钮,然后释放,按钮上将触发
    单击
    事件,但这不是您想要的

    试着玩一下这个片段。它记录每个
    mousedown
    mouseup
    单击
    更改
    事件。它在
    上注册异步
    change
    事件处理程序,第一秒钟不执行任何操作,然后显示覆盖,然后休眠3秒钟,最后隐藏覆盖。您可以根据按住鼠标按钮的时间长短观察各种行为

    更改输入文本并快速单击按钮

    按钮。鼠标向下移动
    输入。更改
    按钮。鼠标点击
    按钮。点击

    更改输入文本,单击按钮并保持1秒,然后释放

    按钮。鼠标向下移动
    输入。更改
    div.mouseup
    正文。单击

    更改输入文本,单击按钮并保持4秒钟(直到覆盖消失),然后重新编辑