문제

I'm trying to do the obvious, update the view on model change (in this case a new one is added). It actually works, but the problem is the whole view gets rerendered when a model is added. The new data is actually not really being appended to the view but pretty much everything is being reloaded using the "html()" method.

Do you know a way to solve this in a more efficient way?

<body>
<div class="page"></div>

    <script type="text/template" id="myTemplate">
        <ul>
            <% for (var i = 0; i < library.length; i++) { %>
                    <li> <%= library[i].title %></li>
                    <li> <%= library[i].artist %></li>
                    <li> <%= library[i].track %></li>  
                <br>
            <% } %>  
        </ul>

        <input id="inputTitle" placeholder="enter title" type="text"> <br>
        <input id="inputArtist" placeholder="enter artist" type="text"> <br>
        <input id="inputTrack" placeholder="enter title" type="number"> <br> 
        <button id="addItem">add</button> 
    </script>

    <script type="text/javascript">

        var Song = Backbone.Model.extend({
            initialize: function()
            {
                this.on('add',function(){
                    albumview.render();
                });
            }
            ,defaults:
            {
                title: "no title",
                artist: "no artist",
                track: 0
            }
        });

        var AlbumView = Backbone.View.extend({
            initialize: function()
            {
                this.render();
            },
            render: function()
            {
                var self = this; 
                var output = _.template($('#myTemplate').html(),{'library': self.collection.toJSON()});

                self.$el.html(output); 
                return self;
            },
            events: 
            { 
                'click #addItem' : 'addItem'
            },
            addItem: function()
            { 
                var TitleValue = $('#inputTitle').val();
                var ArtistValue = $('#inputArtist').val();
                var TrackValue = $('#inputTrack').val();

                var self = this;

                self.collection.push({  
                    title: TitleValue,
                    artist: ArtistValue,
                    track: TrackValue
                });

            }
        });

        var Album = Backbone.Collection.extend({
            model: Song
        });

        var song1 = new Song({
            title: "Trouble on my mind",
            artist: "Pusha-T",
            track: 3
        });

        var song2 = new Song({
            title: "Yonkers",
            artist: "Tyler The Creator",
            track: 2
        });

        var album = new Album([song1,song2]);

        var albumview = new AlbumView({
            el: '.page',
            collection: album
        });

    </script>
</body> 
도움이 되었습니까?

해결책

First, I'd avoid calling your view's render method from inside the model. Second, are you sure you want a new albumview for each song? It seems like your albumview, which maintains a reference to your album collection, just needs a songview, or some other such construct:

var AlbumView = Backbone.View.extend({
    initialize: function () {
        this.listenTo(this.collection, 'reset', this.render);
        this.listenTo(this.collection, 'add', this.addOne);
    },
    render: function () {
        this.addAll();
        return this;
    },
    addAll: function () {
        this.$el.empty();
        this.collection.each(this.addOne, this);
    },
    addOne: function (song) {
        var songView = new SongView({ model: song });
        this.$el.append(songView.render().el);
    }
});

var SongView = Backbone.View.extend({
    render: function () {
        // whatever you would do for just one song
    }
});

This is a common pattern for rendering a collection (album) view and an item (song) view.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top