【问题标题】:Backbone double posting issue骨干双张贴问题
【发布时间】:2013-12-21 12:57:01
【问题描述】:

我有一个奇怪的 Backbone 问题,可能与 Backbone 的工作方式有关,我还不明白。

我有一个带有转到其他路线的按钮的主屏幕。如果我单击一个并转到那条路线,一切正常。如果我返回菜单并单击同一条路线,则每个单击事件都会运行两次。如果我每次点击事件都运行三次......等等,等等

为什么会这样?我错过了什么?

菜单页面链接:

<a class="btn btn-large homebutton" id="addcrateslink" data-href="/#/crateadd">Add Crates To New Location</a>

在该链接上触发的事件:

    events: {
        "click .homebutton":"redirect"
    },

    redirect: function(e) {
        e.preventDefault();
        // Get details
        var href = $(e.currentTarget).data("href");
        console.log("Href", href);
        Backbone.history.navigate(href.replace("#",""));
    },

路由器如何处理该路由:

    addcrate: function (eventname) {
        var self = this;
        this.showLoading();
        $("#contentitems").html(" ");
        this.ensureLogin(function(){
            if (self.crateCollection.length > 0 && self.crateCollection !== null)
            {
                var addCrateView = new AddCrateView({model: self.crateCollection, unused: self.unusedCrateCollection, eventtype: eventname });
                addCrateView.on('render', self.hideLoading());
            }
            else
            {
                //Set Up Sort
                self.fetchCrates(function (){
                    console.log("in the fetchcratescallback");
                    var addCrateView = new AddCrateView({model: self.crateCollection, unused: self.unusedCrateCollection, eventtype: eventname });
                    addCrateView.on('render', self.hideLoading());
                });
            }

        });
    },

查看该路线的负载:

var AddCrateView = Backbone.View.extend({
    template: _.template(AddCrateTemplate),
    el: "#contentitems",
    utils: new Utils(),
    model: new CrateCollection(),

    initialize: function (models) {
        this.location = models.thelocation;
        if (this.location === null || typeof this.location === "undefined")
        {
            this.location = this.utils.readCookie("location");
        }
        this.destination = this.utils.readCookie("destination");
        this.eventtype = models.eventtype;
        this.crate = models.thecrate;
        this.crateCollection = models.model;
        this.unusedCrates = models.unused;
        this.locationCollection = new LocationCollection();            
        var me = this;
        this.locationCollection.fetch({
            success: function () {
                me.render();
                me.on("render", me.utils.showHideContent());            
            },
            error: function () {
                me.utils.sendAlert("Uh-Oh!", "There was an error loading this page.  Please hit refresh (F5 or CTRL-R).", "error", function(){});
            },
        });
    },

    events: {
        "click #addnewcrate": "createCrate",
        "click #clearlocation": "clearlocation",
        "click #cleardestination": "cleardestination",
        "click #cratelocationscanlink": "locationscan",
        "click #cratescanlink": "cratescan",
        "click #cratedestinationscanlink": "destinationscan",
    },

    showLoading: function () {
        ...
    },

    hideLoading: function () {
        ...
    },

    createCrate: function (eventname) {
        ...
    },

    validateForm: function (currentCrate, unusedCrate) {
        ...
    },

    render: function () {
        var self = this;
        $(this.el).html(this.template({url: this.utils.getDomain() }));

        var typeaheadLocation = new TypeaheadLocation({ collection: this.locationCollection, key: 'Name' });
        typeaheadLocation.setElement('#locationtaholder').render();

        var typeaheadDestination = new TypeaheadDestination({ collection: this.locationCollection, key: 'Name' });
        typeaheadDestination.setElement('#destinationtaholder').render();

        if (typeof this.location !== "undefined" && this.location !== "") {

            var setLocation = this.locationCollection.findWhere({ Name: this.location });

            if (typeof setLocation !== 'undefined') {
                $("#cratescanfalselink").addClass("item-hidden");
                $("#cratescanlink").removeClass("item-hidden");

                $('#location').val(setLocation.get("Name"));
                $('#clearlocation').removeClass("item-hidden");

                if (typeof this.crate !== "undefined") {
                    // Send the crate to the DB
                    $('#name').val(this.crate);
                    self.createCrate();
                }
            }
            else
            {
                self.utils.sendAlert("Location Error!", "Error setting location: It appears that this location does not exist in the system.", "error", function(){});
            }
        }

        // Set destination
        if (typeof self.destination !== "undefined" && self.destination !== "") {

            var setDestination = self.locationCollection.findWhere({ Name: self.destination });

            if (typeof setDestination !== 'undefined') {
                $('#destination').val(setDestination.get("Name"));
                $('#cleardestination').removeClass("item-hidden");
            }
            else
            {
                console.log("In wrong destination catch...");
                self.utils.sendAlert("Location Error!", "Error setting destination: It appears that this destination does not exist in the system.", "error", function(){});
            }
        }

        this.testtype();
    },

    showRemainingCrates: function(currentLocation, newlocation){
        ...
    },

    clearlocation: function () {
        ...
    },     

    cleardestination: function () {
        ...
    },

    testtype: function() {
        ...
    },

    locationscan: function (e) {
       ...          
    },

    destinationscan: function (e) {
       ...           
    },

    cratescan: function (e) {
       ...          
    }

});

【问题讨论】:

  • 发布相关脚本,我最好的心理猜测是您错误地渲染了视图模板。
  • :-) 好点。 (只是觉得这很明显是我错过了)我已经添加了代码......
  • 只是一个猜测...您是否尝试过调用视图的 remove() 方法,然后再针对同一视图的后续请求再次创建它?这应该取消绑定任何事件侦听器。
  • @NathanHarkenrider:他需要覆盖 remove 以将 this.$el.remove() 替换为 this.$el.empty()this.undelegateEvents()

标签: backbone.js


【解决方案1】:

听起来您可能遇到了僵尸视图问题。您的旧视图可能没有被清理。

一种策略是在您的路由器中创建一个变量来保存对当前视图的引用。在加载另一个视图之前,请检查该变量中是否有视图,如果有,请在添加新视图之前对其进行call remove

这应该将其从 DOM 中完全删除,并取消绑定其中的任何事件。

if (currentView && 'remove' in currentView) {
  currentView.remove();
}

【讨论】:

  • 好的。因此,当我完成视图时,我需要删除和取消绑定视图。我似乎无法在我的路由器中访问它们......例如,如果 (this.addCrateView) 在路由器的 addCrate 函数中返回 false。
  • 不用担心...我刚刚创建了一个主路由器视图,我将视图加载到其中,因此每次加载新视图时我都可以访问它。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
相关资源
最近更新 更多