如何在呈现Backbone模板后调用jQuery代码?

时间:2013-12-19 10:59:11

标签: jquery backbone.js underscore.js backbone-events

我正在使用Backbone.js(使用Underscore模板),Express和Node.js构建应用程序。

我用这个非常简单的例子来说明问题(见下面的代码),应用程序包含从服务器检索到的“标题”列表。

我使用下划线模板来呈现HTML。在呈现HTML之后,我想执行一些jQuery代码,例如在控制台中打印每个“标题”的position()。 问题是在模板将元素插入DOM之前调用jQuery代码,因此jQuery无法找到元素。

我错过了什么? 在将DOM插入DOM后,是否有办法获取事件?

这里是代码:

    <div class="container">
        <div id="tracks">

        </div>
    </div>

    <!-- Template -->
    <script id="trackTemplate" type="text/template">

        <ul id="<%= id2 %>" style="height:150px">
            <li><%= title %></li> 
        </ul>               

        <%
        // So it looks like this code gets code before the template's HTML is in the DOM.
            console.log($("#"+id2).position());
        %>
    </script>

    <script src="js/lib/jquery-1.10.2.min.js"></script>
    <script src="js/lib/underscore-min.js"></script>
    <script src="js/lib/backbone-min.js"></script>
    <script>
    var app = app || {};

    // Model
    app.Track = Backbone.Model.extend({
        defaults: {
            id2: '',
            title: 'Track',
        },
    });

    // Collection
    app.Library = Backbone.Collection.extend({
        model: app.Track,
        url: '/api/tracks' 
    });

    // Track view
    app.TrackView = Backbone.View.extend({
        tagName: 'div',
        className: 'trackContainer',
        template: _.template( $( '#trackTemplate' ).html() ),
        initialize:function(){
            this.model.on('change', this.render, this);
        },
        render: function() {
            this.$el.html( this.template( this.model.toJSON() ) );

            return this;
        },

    });

    // Collection View
    var numberOfTracks = 0;
    app.LibraryView = Backbone.View.extend({
        el: '#tracks',

        initialize: function( initialTracks ) {
            this.collection = new app.Library( initialTracks );
            this.collection.fetch(); 
            this.listenTo( this.collection, 'add', this.renderTrack);
        },

        // render library by rendering each track in its collection
        render: function() {
            this.collection.each(function( item ) {
                this.renderTrack( item );
                numberOfTracks++;
            }, this );
        },

        // render a track by creating a trackView and appending the
        // element it renders to the library's element
        renderTrack: function( item ) {
            var trackView = new app.TrackView({
                model: item
            });
            this.$el.append( trackView.render().el );
        },
    });

    // Initialise app
    var libraryView =  new app.LibraryView();
    </script>

由于

2 个答案:

答案 0 :(得分:1)

为了覆盖这里的某些内容,一旦将某些内容插入DOM中,就不会触发事件。我实际上并不主张通过将代码放入模板中来试图解决这个问题。而是看看你的视图呈现方式。

如果你想把一些代码扔进一个预先存在的占位符,你可以看看做这样的事情:

[view here].setElement(this.$([selector here])).render();

对此有一个很好的解释:

http://ianstormtaylor.com/rendering-views-in-backbonejs-isnt-always-simple/

如果您不需要任何重量级的子视图管理,这是一种安排子视图的简洁方法。你应该在那之后能够使用jquery做一些事情,正如你通常在视图中使用这个。$ el和this。$。在视图中正确确定元素的范围。

答案 1 :(得分:0)

  • console.log电话的正确位置将在render方法的最后或renderTrackappend之后。

  • Backbone还可以轻松创建自己的活动并通过Backbone.Events注册。你可以在我在前一段中提到的地方之一发起自己的事件。

  • 有一个不推荐使用的事件系列用于跟踪名为Mutation events的DOM中的更改 - 但它们已弃用且浏览器支持不太可靠。替换是MutationObserver,在DOM4 spec中定义,浏览器支持尚不存在(IE仅支持11)但是对于测试它可能有用。

  • 另一种方法是将您的代码放在setTimeout中 - 这样,您console.log运行时肯定会插入DOM节点。