单击是在骨干中调用两次函数

fer*_*vak 10 templates view duplicates backbone.js

我已经在主干View上创建了两次警报触发的快速示例.

http://jsfiddle.net/feronovak/8svqX/

这没什么特别的,它真的让我理解如何正确调用单独的视图,所以它们不会触发先前的点击方法.现在我生成两个视图,第二个视图覆盖#boxSearch中的表单.当我点击按钮搜索时,它也会生成警报doSearch SearchLocation.我期待只看到警报doSearch SearchLatitude.我做错了什么?

var Geo = {
    Views: {},
    Templates: {}
};

Geo.Templates.SearchLocation = _.template( $("#tpl-search-location").html());
Geo.Templates.SearchLatitude = _.template( $("#tpl-search-latitude").html());

Geo.Views.SearchLocation = Backbone.View.extend({
    initialize: function() {
        this.render();
    },
    el: $("#boxSearch"),
    template: Geo.Templates.SearchLocation,
    render: function() 
    {
        $(this.el).html(this.template);
    },
    events: {
        "click input[type=button]": "doSearch"
    },
    doSearch: function(e) {
        e.preventDefault();
        alert('doSearch SearchLocation');
    }
});

Geo.Views.SearchLatitude = Backbone.View.extend({
    initialize: function() {
        this.render();
    },
    el: $("#boxSearch"),
    template: Geo.Templates.SearchLatitude,
    render: function() 
    {
        $(this.el).html(this.template);
    },
    events: {
        "click input[type=button]": "doSearch"
    },
    doSearch: function(e) {
        e.preventDefault();
        alert('doSearch SearchLatitude');
    }
});

$(document).ready(function(e) {
    var searchLocation = new Geo.Views.SearchLocation();
    var searchLatitude = new Geo.Views.SearchLatitude();
});
Run Code Online (Sandbox Code Playgroud)

nra*_*itz 19

这是Backbone应用程序常见的"鬼视图"问题:

  • 您将视图附加到DOM元素
  • 您将另一个视图附加到同一个DOM元素
  • 您在DOM元素上触发事件(或者更糟糕的是,在两个视图都侦听的其他地方触发事件)
  • 两个视图都会激活他们的事件处理程序,经常造成严重破坏.

正如@machineghost指出的那样,你的代码中没有任何内容可以取消绑定第一个视图,因此两个视图都被附加到#boxSearch,并且两个视图都将响应该click事件.有几种方法:

  • 你可以在事件处理程序中调用e.stopPropagation()(docs)(我认为这是你正在尝试做的事情e.preventDefault()).这将防止事件在触发后冒泡,因此最后定义的视图将捕获它.这有效,但请注意,您仍然可以看到两个视图,过时的鬼视图可能还有其他副作用.

  • 您可以让每个视图使用类呈现自己的DOM元素,.boxSearch然后调用view.remove()您不再需要的视图.这可能是最干净的选择,但它意味着动态创建大多数DOM,这比用HTML编码更昂贵,更难管理.

  • 你可以给每个视图一个清理方法,例如,.clear()或者.exit()可以调用view.undelegateEvents()view.stopListening().然后确保在完成视图后调用此方法.

如果你小心确保它被调用并确保它清除了所有需要清除的东西,那么它运作良好.