用于复选框和标签的骨干视图事件处理程序

Mar*_*ark 4 javascript backbone.js

我试图找出一个复选框ID是否在用户点击它之后没有被扯掉.checkox包裹在一个必须可点击的标签中.我的代码是:

<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>
Run Code Online (Sandbox Code Playgroud)

回答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") });
Run Code Online (Sandbox Code Playgroud)

jsfiddle在这里.

有一些问题.如果我单击输入,它工作正常,值为isCheckedtrue.但是,如果我单击标签,该函数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
Run Code Online (Sandbox Code Playgroud)

所以isChecked第一次是假的.

那么,无论是否用户点击标签或直接在输入上,我如何知道是否正在选中复选框?当用户点击标签时,如何阻止处理程序执行两次?

T J*_*T J 9

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

  • 实际点击 <label>
  • 单击<input>标签触发.

因此,如果我们在标签上收听点击事件,我们将在这种情况下捕获它们 - 因为触发的点击<input>也会冒泡,<label>因为它是父母.

我们可以通过点击复选框本身而不是标签来解决这个问题.

您可以使用is带有:checkbox:checked选择器的jQuery 方法执行以下操作,如下所示.

    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")
});
Run Code Online (Sandbox Code Playgroud)

更新了小提琴

请注意,缓存模板函数是一种很好的做法,而不是_template每次调用渲染时调用.