【问题标题】:How to avoid double event binding in Backbonejs View?如何避免 Backbonejs 视图中的双重事件绑定?
【发布时间】:2016-05-15 20:12:00
【问题描述】:
var RowView = Backbone.View.extend({
    tagName: 'li',
    className: 'course-row',
    events: {
        "click .table-row": "rowClick" // problem here!
    },
    initialize: function() {},
    template: _.template(tpl),
    render: function() {

        var rowStr = this.template({course: this.model});
        $(this.el).append(rowStr);
    },
    rowClick: function (e) {
        alert(e);
    }
});

上面的代码定义了一个 Backbone Row 视图。我想在一个表中创建并呈现几行,所以我做到了:

data.forEach(function(rowData){
    var row = new RowView({model: course, el: mountPoint});
    row.render();
});

如果我创建 2 行,则事件绑定两次(如果单击该行,则绑定 2 个警报消息),3 行 3 次。我通过在父视图中定义事件来避免这个问题,但是如果我真的需要在每一行附加事件处理程序,我该如何避免双重事件投标问题?

【问题讨论】:

  • this answer 中有一些父/子视图的策略。但也不要错过更远的pub/sub answer
  • 这不应该发生。你能创建一个minimal reproducible example..吗?
  • tagNameclassName 在您的RowView 中的存在表明RowView 创建了自己的el。但在这种情况下,一个简单的row.render() 不会在页面上得到任何东西。此外,双重事件表明您将多个视图绑定到同一个el。这些事情表明这不是你真正的forEach 循环。我错过了什么?
  • @muistooshort 我使用“new RowView({model: course, el: mountPoint});”创建视图,因此在渲染时,行将在页面上呈现自身。我刚刚更新了我的问题以解决您的问题。谢谢!
  • @TJ:只是旧的“我将一个el 用于多个视图”问题再次出现,这解释了 Backbone 中 90% 的“一个事件被多次触发”错误。

标签: javascript backbone.js


【解决方案1】:

你正在这样做:

data.forEach(function(rowData){
    var row = new RowView({model: course, el: mountPoint});
    row.render();
});

这意味着您的视图将忽略它的 tagNameclassName 并继续将自己绑定到您提供的 el because

this.el 可以从 DOM 选择器字符串或元素中解析;否则将从视图的tagNameclassNameidattributes 属性创建。

一个视图的events are bound to its el using delegation 并且您正在绑定多个视图(恰好是同一个视图“类”),所以您当然会获得多个事件绑定。

如果你的行真的应该是 <li class="course-row"> 元素,那么你想做几件事:

  1. RowViews 创建并拥有自己的els。将tagNameclassName 属性保留在RowView 中,并停止将el 传递给构造函数。您也应该将$(this.el) 更改为this.$el,当Backbone 已经为您隐藏了一个jQuery 对象时,无需创建另一个jQuery 对象。

  2. RowViewrender 返回this,这是标准做法,可以让下一步更好一些。

  3. 无论创建你的RowViews 什么都应该创建它们,render 它们,然后将它们放入容器中。您似乎正在尝试使用mountPoint(可能是<ul>)作为容器,所以您想说:

    data.forEach(function(rowData) {
        var row = new RowView({model: course});
        mountPoint.append(row.render().el);
        // This is why (2) above -----^^^
    });
    

    假设 mountPoint 是一个 jQuery 实例,如果不是这种情况,那么你会想说 $(mountPoint).append(row.render().el) 代替(或者在 forEach 上方使用 var $mountPoint = $(mountPoint) 并在其中使用 $mountPoint.append) .

个人经验法则:如果您将el 传递给视图构造函数,那么您几乎肯定会犯错误。如果你确切地知道为什么要将 el 传递给构造函数,知道后果,并且知道如何处理它们,那么你已经足够成熟,可以用剪刀跑了,所以继续吧。

【讨论】:

    猜你喜欢
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多