复选框和标签的 Backbone.js 视图事件处理程序

ttcibm8c  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(136)

我试图找出一个复选框在用户点击后是否被选中。复选框被 Package 在一个标签中,这个标签也必须是可点击的。我的HTML代码是:

<div id="view_container">a</div>

<script type="text/template" id="view_template">
  <ul>
        <li>
            <label>
                <input type="checkbox" checked="" value="a">A option
           </label>
        </li>
        <li>
            <label>
              <input type="checkbox" value="b">B option
            </label>
       </li>
        <li>
           <label>
             <input type="checkbox" value="c">C option
          </label>
        </li>
     </ul> 
</script>

响应JavaScript:

View = Backbone.View.extend({
  initialize: function() {
    console.log('in the init');
    this.render();
  },
  render: function() {
    var template = _.template($("#view_template").html(), {});
    this.el.html(template);
  },
  events: {
    'click ul li label': 'clicked',
  },

  clicked: function(e) {
    e.stopPropagation();

    console.log('e.target is ' + e.target);
    console.log('e.currentTarget is ' + e.currentTarget);

    var isChecked = $(e.currentTarget).find('input:first').is(':checked');
    var selected = $(e.currentTarget).find('input:first').val().trim();

    console.log('isChecked is ' + isChecked);

  },
});

var view = new View({
  el: $("#view_container")
});

jsfiddle是here
有几个问题。如果我点击输入,它工作正常,isChecked的值为真。但是,如果我点击标签,函数clicked执行两次,console.log输出为:

e.target is [object HTMLLabelElement]
e.currentTarget is [object HTMLLabelElement]
isChecked is false
e.target is [object HTMLInputElement]
e.currentTarget is [object HTMLLabelElement]
isChecked is true

所以isChecked第一次是假的。
那么,无论用户是点击标签还是直接点击输入,我如何知道复选框是否被选中?当用户点击标签时,我如何阻止处理程序执行两次?

zaqlnxep

zaqlnxep1#

问题在于,本质上,包含<input>的标签或通过for属性连接到它们的标签会在相关输入上触发单击事件。因此,有2个单击事件:

  • 实际点击<label>
  • 标签在<input>上触发点击。

因此,如果我们侦听label上的click事件,我们将在本例中捕获这两个事件-因为在<input>上触发的click也将冒泡到<label>,因为它是父级。
我们可以通过听复选框本身的点击来解决这个问题,而不是听标签。
您可以使用jQuery is方法和:checkbox:checked选择器来执行以下操作,如下所示。

View = Backbone.View.extend({
    initialize: function () {
        this.render();
    },
    template: _.template($("#view_template").html()),
    events: {
        'click ul li :checkbox': 'clicked',
    },
    render: function () {
        this.$el.append(this.template({}));
    },
    clicked: function (e) {
        var $target = $(e.target);
        var selected = $target .is(':checked');
        console.log('selected: ', selected, 'value: ', $target.val());
    }
});

var view = new View({
    el: $("#view_container")
});

Updated fiddle
请注意,最好缓存模板函数,而不是每次调用render时都调用_template

0lvr5msh

0lvr5msh2#

请在这里看到最好的答案Why Does a Label Inside an Input Trigger a Click Event。简而言之,它是标签元素的规范。

相关问题