Backbone在多次渲染时查看事件不起作用

时间:2015-03-26 16:58:07

标签: jquery events dom backbone.js parse-platform

我有一个问题,我无法很好地理解Backbone视图事件。 几个星期前,我遇到了" multiple views events triggering"问题,因为我将所有视图元素附加到现有且永不压缩的DOM元素(我的页面架构中为#page_content,见下文),并且我没有手动清理视图和事件)。

由于我不想手动进行清洁,不是懒惰,但因为我发现它容易出错,我最终得到了一个很好的解决方法,就是永远不要将我的观点附加到现有的DOM元素。因此,我只使用tagNameclassName来创建我的视图元素,然后将其插入到现有DOM元素中(通常在#page_content内,见下文)。由于Backbone删除了事件监听器(如果它们所附着的DOM元素被删除),并且如果它们的元素从DOM中删除,垃圾收集视图,我发现这是处理视图及其事件的一种非常简洁的方法。

所以......直到今天,这一直很好。在我的一个视图中,我调用了两次render函数。第一次调用render函数时,一切正常。触发事件并按预期捕获。但是,如果我第二次调用render函数,则不再触发任何视图事件。

以下是我的观点模板:

  <script type="text/template" id="chat_selection_template">
    <div class="push_me_down side_pad_me">
      <div id="schools_chat_container">
        <h2>Chat par école:</h2>
        <ul>
        <% if (schools) { %>
          <% for (var i=0; i<schools.length; i++) { %>
          <li class="school">
            <a href="/chat/school/<%= schools[i].id %>" class="mlb_text blue">
              <%=  schools[i].attributes.appellation_officielle_uai %>Rejoindre ce chat
              <i class="fa fa-chevron-right"></i>
            </a>
          </li>
          <% } %>
        <% } else { %>
          <li class="empty">Vous n'êtes assigné(e) à aucune école pour le moment. <a class="mlb_text blue" href="/select_lines">Sélectionner une école à laquelle emmener vos enfants en Pédibus</a>.</li>
        <% } %>
        </ul>
      </div>

      <div id="lines_chat_container">
        <h2>Chat par ligne:</h2>
        <ul>
        <% if (lines) { %>
          <% for (var i=0; i<lines.length; i++) { %>
            <li class="line"><%=  lines[i].attributes.start_point_name %> - <%= lines[i].attributes.schoolName %> <a href="/chat/line/<%= lines[i].id %>" class="btn btn-mlb">Rejoindre ce chat</a></li>
          <% } %>
        <% } else { %>
          <li class="empty">Vous n'êtes inscrit(e) à aucune ligne pour le moment. <a class="mlb_text blue" href="/select_lines">Inscrire mon enfant à une ligne de Pédibus</a>.</li>
        <% } %>
        </ul>
      </div>
    </div>
  </script>

这是JS:

      // Chat selection page View
  MLB.ChatSelectionView = Parse.View.extend({

    tagName:        'div',
    className:      'chat_selection_container',
    template:       _.template($("#chat_selection_template", MLB.TEMPLATES).html()),
    schools:        false,
    lines:          false,


    events : {
      "click #select_school_link":  "go_select_a_school", 
    },


    initialize : function() {
      var School        = Parse.Object.extend("School");
      var school_query  = new Parse.Query(School);
      var current_user  = Parse.User.current();
      var Line          = Parse.Object.extend("Route");
      var line_query    = new Parse.Query(Line);
      var self          = this;


      school_query.equalTo("parents", current_user);
      school_query.find().then(
        function(schools) {
          if (schools.length > 0) {
            self.schools = schools;
          }
          self.render();
        },
        function(error) {
          MLB.log_to_parse("middle",'chat_selection', 'Failed to retrieve schools.');
          self.render();
        }
      );


      line_query.equalTo("contributors", current_user);
      line_query.find().then(
        function(lines) {
          if (lines.length > 0) {
            self.lines = lines;
          }
          self.render();
        },
        function(error) {
          MLB.log_to_parse("middle",'chat_selection', 'Failed to retrieve lines.');
          self.render();
        }
      );
    },


    go_select_a_school: function(event) {
      event.preventDefault();
      Parse.history.navigate("consult_lines", {trigger: true});
    },


    render : function(schools) {
      this.$el.html( this.template({schools: this.schools, lines: this.lines}) ); 
      MLB.CONTENT.html(this.$el);
    },
  });

这是我的应用HTML架构:

<html>
<head></head>
<body>
  <div id="content-wrapper">

    <header id="page_header">
      <div class="wrapper">
        <h1 class="logo">
          <a href="/" id="header_homepage">PetitBus</a>
        </h1>

        <div id="header_login"></div>
      </div>
    </header>

    <div id="fb-root"></div>
    <div id="page_content"></div>


    <!-- TEMPLATES -->
    <div id="templates">
       [Backbone templates code]
    </div>
</body>
</html>

我想理解为什么第二次调用render函数会搞砸所有问题。由于我对看到后面发生的事情的理解有限,所以当发生这种情况时,第一个渲染中的所有DOM元素都会被删除,他们的事件监听器也是如此。但随后插入了新的DOM元素,他们的事件监听器也是如此......对吗?至少这是我所期待的,但似乎我错了。

对此非常欢迎。我想在冲向错误的方向之前深刻理解这里发生了什么。

非常感谢

1 个答案:

答案 0 :(得分:1)

添加this.delegateEvents();作为渲染功能的最后一行。

  

Backbone文档:“默认情况下,在其中调用delegateEvents   View的构造函数,所以如果你有一个简单的事件哈希,   您的所有DOM事件将始终已连接,您将会这样做   永远不必亲自调用此功能。“

因此,如果您第二次渲染视图,则需要自己调用delegateEvents,因为不会再次调用构造函数。