Backbone: повторяющиеся события при создании экземпляра представления дважды

Созданный на 5 февр. 2012  ·  9Комментарии  ·  Источник: jashkenas/backbone

Когда я определяю представление (через Backbone.View.extend) и создаю его дважды (через new), когда событие происходит один раз на каждом объекте ivies, оно запускается дважды.

Краткий пример:

<html>
<head>
    <script type="text/javascript" src="js/jquery-1.7.1.js"></script>
    <script type="text/javascript" src="js/underscore-1.3.1.js"></script>
    <script type="text/javascript" src="js/backbone-0.9.1.js"></script>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript">
        testview = Backbone.View.extend ({
            el: '#test',
             events: {'click .test': 'doTest'},
             doTest: function() {alert('test')},
             render: function() {$('#test').append($('<a>').attr('href', '#').addClass('test').append('test'));}});
        view_one = new testview;
        view_two = new testview;
        view_one.render();
    </script>
    </body>
</html>

Все 9 Комментарий

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

Что-то такое. У меня есть домашнее представление, которое будет вызывать разные конечные точки, если пользователь вошел в систему или нет. Привязки событий предназначены для кнопок входа / выхода. Созданы экземпляры обоих представлений, но одновременно отображается только одно. Когда они входят в систему или выходят из системы, я переключаюсь на то же представление, но в другом режиме. Надеюсь, это достаточно ясно.

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

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

Что ж, казалось хорошей идеей создать экземпляры обоих представлений во время инициализации, привязать оба к одному и тому же корневому элементу в DOM, а затем отрендерить один или другой в соответствии с режимом входа в систему и заставить его заменить другие элементы во время визуализации. Я думаю, что есть лучший способ сделать это, судя по вашим комментариям.

Я бы создал экземпляры представлений, когда они вам понадобятся. Если представление не используется, нет необходимости в том, чтобы оно занимало память и потенциально создавало побочные эффекты, как вы видите.

Я стараюсь не использовать этот шаблон:

var View = Backbone.View.extend ({
    el: '#test',
    events: 
    {
        'click .test': 'onClick'
    },
    onClick: function(event) 
    { 
        ... 
    }
});

view = new View;
view.render();

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

var View = Backbone.View.extend ({
    events: 
    {
        'click .test': 'onClick'
    },
    onClick: function(event) 
    { 
        ... 
    }
});

view = new View;
$('#target').append(view.render().el);

Единственное место, где я бы использовал ваш первый шаблон, - это представление Chrome приложения, которое создает экземпляр графического интерфейса:

var Application = Backbone.View.extend({
    el: '#wrapper',
    initialize: function (options)
    {
        this.render();
    }
)};

$(document).ready(function () {
    window.application = new Application();
});

То же касается того, что сказал отказе от определения el и о разрешении представлению генерировать собственный элемент. Я тоже так делаю в 95% случаев. Однако, если вы хотите определить el и очистить события при удалении, вы можете определить свой собственный метод Backbone.View.destroy() с помощью .off() для каждого соответствующего on() и каждое событие в events: {}

Например:

var MyView = Backbone.View.extend({

  initialize: function() {
    this.model.on('change', this.render, this);
  },

  render: function() {
    return this;
  },

  destroy: function() {
    this.remove();
    this.model.off('change', this.render, this);
  }
})

Спасибо, @malandrew и @vincentbriglia , это действительно помогает.

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

           destroy: function() {
                this.undelegateEvents();
            }

Затем я просто уничтожаю текущее представление (State.view) всякий раз, когда создаю экземпляр ().

Была ли эта страница полезной?
0 / 5 - 0 рейтинги