Магические события, стреляющие дважды

Почему я должен создать целостный закрыть прототип, чтобы мои события были неотчеркнуты из моего представления? Должна ли Магний не строить это? Есть ли способ обнаружить, когда вид удаляется?

Мои главные события срабатывают дважды после того, как я перейду и вернусь к просмотру.

        events : {
            "click #userDropdownButton > a" : "toggleUserDropdownMenu",
            "click" : "hideUserDropdownMenuIfClickedOutside"
        },

        el : "body",

        initialize : function() {
            this.render();
        },

        // Shows/hides the user dropdown menu
        toggleUserDropdownMenu : function() {
            if(!this.$el.find('#userDropdownButton > ul').is(':visible')) {
                this.showUserDropdownMenu();
            } else {
                this.hideUserDropdownMenu();
            }
            return false;
        },
        showUserDropdownMenu : function() {
            this.$el.find('#userDropdownButton').addClass('hover');
            this.$el.find('#userDropdownButton > ul').show();
            this.$el.find('#userDropdownButton > a .arrow-down').removeClass('arrow-down').addClass('arrow-up');
        },
        hideUserDropdownMenuIfClickedOutside : function() {
            if(this.$el.find('#userDropdownButton > ul').is(':visible')) {
                this.hideUserDropdownMenu();
            }
        },
        hideUserDropdownMenu : function() {
            this.$el.find('#userDropdownButton').removeClass('hover');
            this.$el.find('#userDropdownButton > ul').hide();
            this.$el.find('#userDropdownButton > a .arrow-up').removeClass('arrow-up').addClass('arrow-down');
        },

При первом просмотре представления раскрывающееся меню открывается и закрывается должным образом, но во второй раз, когда визуализируется представление, выпадающее меню интерпретирует каждый щелчок дважды, поэтому, как только он открывается, второй щелчок закрывает его.

Ответ 1

Обновление 2013/05/01: Backbone 0.9.9+ добавила некоторые встроенные функции для облегчения работы с проблемой zomg (см. View.remove и StopListening); но вам все равно нужно убить своих зомби, позвонив одним из них.


Почему я должен создать цельный прототип только для того, чтобы мои события были не привязаны к моему представлению?

Derick article является удивительным при освещении всей этой проблемы. Но я могу добавить свои два бита, обращаясь к вашему вопросу о том, "почему" он не встроен.

Из-за того, как работает делегирование событий Backbone, представления не будут собираться мусором, когда они выходят за пределы области видимости, если у них есть привязки к событиям. Это связано с тем, что объекты, чьи события привязаны к объектам Backbone, в случае привязки к событиям объекта Backbone или к системе событий DOM в случае обратных вызовов событий - поддерживают ссылки на функции представления.

Верьте или нет, некоторые пользователи Backbone полагаются на это поведение и ожидают, что представления продолжат автоматическое реагирование на события, как им сказали, даже если они полностью вышли из сферы действия. (Я видел несколько учебников, которые делают это.) Это предполагает, что вам никогда не нужно удалять представление или что представление может реагировать на события и удалять себя, поскольку вы потеряли какую-либо ссылку на него, но IMO, создавать и забывать "функциональность хороша, пока вы понимаете последствия.

mu is too short дает хорошее представление о событиях пользовательского интерфейса. Удаление el из DOM также должно удалить делегированные события. То же самое нельзя сказать о привязке к событиям модели или коллекции или к другим событиям объектов Backbone (любой объект может распространять прототип Backbone Events). Вам нужно будет следовать совету Derick Bailey в статье, на которую вы ссылаетесь и вручную закрываете представление в этих случаях. Я не уверен, что это слабость базовой сети по сравнению с другими структурами JS MVC, я не пробовал других как в глубине.

"Есть ли способ обнаружить, когда удаляется вид?"

Не прямо, что я знаю. Но в целом, какой бы код не удалял просмотр, также следует очищать привязки событий, если это необходимо. Часто в хороших архитектурах MVC представления могут настраивать наблюдателя событий на соответствующей модели или коллекции, а затем удалять и очищать себя на основе происходящего события (например, событие "удалить" из соответствующей модели). Если вы хотите, чтобы вы полностью удалили ваши представления "обнаружимыми", одним из способов было бы переопределить функцию удаления в вашем собственном прототипе представления и вызвать настраиваемое событие, которое можно наблюдать другими.