更新集合时如何更新模板的一部分?

时间:2016-10-27 18:16:04

标签: javascript jquery html backbone.js

我尝试在更新集合时仅更新Backbone视图使用的模板的一部分。以下代码成功执行search()render_list()方法。此外,console.log(html)会显示完整模板的HTML。但是当我执行replaceWith时,它会将选择器替换为空。如果我用字符串替换$(selector,html)(例如:' test'),它会成功替换为' test'。

因此,出于某种原因,$(selector, html)选择器并没有做到它的意思。更奇怪的是,即使没有更新的html插入到文档中,浏览器也会请求更新的html选择器中的图像。

define([
    'jquery',
    'underscore',
    'backbone',
    'collections/tracks',
    'collections/genres',
    'text!templates/search_view_title.html',
    'text!templates/search_view.html'
],function($,_,Backbone,Tracks_collection,Genres_collection,Search_view_title_template,Search_view_template){
    var Search_view = Backbone.View.extend({
        el: $('#app'),
        events: {
            'change #genre_select': function(){this.search('genre')},
            'click #search_btn': function(){this.search('search')}
        },
        template: _.template(Search_view_template),
        initialize: function(){
            // SET SOME IMPORTANT LAYOUT SETTINGS
            $('#pagetitle').html(_.template(Search_view_title_template));
            $('body').css('padding-top','124px');

            this.genre_collection = new Genres_collection();
            this.listenTo(this.genre_collection,'update',this.render);
            this.genre_collection.fetch();

            this.collection = new Tracks_collection();
            this.listenTo(this.collection,'update',this.render_list);

        },
        search: function(searchtype){
            switch(searchtype){
                case 'genre':
                    console.log('genre changed');
                    this.collection.fetch({
                        data: {limit: 30, type:'genre',genre_id:$('#genre_select').val()}
                    });
                break;
                case 'search':
                    console.log('search changed');
                    this.collection.fetch({
                        data: {limit: 30, type:'search',keyword:$('#keyword').val()}
                    });
                break;
            }
            console.log(this.collection);

        },
        render_list: function(){
            var that = this;
            console.log('render list');
            var html = that.template({genres: this.genre_collection.models,tracks: this.collection.models});
            console.log(html);
            var selector = '#tracklist';
            console.log($(selector,html));
            that.$el.find(selector).replaceWith($(selector,html));
            return this;
        },
        render: function(){
            // MAKE 'THIS' ACCESSIBLE
            var that = this;
            console.log('render');

            that.$el.find('#container').html(that.template({genres: this.genre_collection.models}));

            return this;
        }
    });

    return Search_view;

});

1 个答案:

答案 0 :(得分:1)

如果没有HTML模板,我可以假设。

这是更接近我将如何做到:

var Search_view = Backbone.View.extend({
    el: $('#app'),
    events: {
        'change #genre_select': 'onGenreChange',
        'click #search_btn': 'onSearchClick'
    },
    template: _.template(Search_view_template),
    initialize: function() {
        // SET SOME IMPORTANT LAYOUT SETTINGS
        $('#pagetitle').html(Search_view_title_template);

        // Do this in css
        $('body').css('padding-top', '124px');

        this.genre_collection = new Genres_collection();
        this.genre_collection.fetch();

        this.collection = new Tracks_collection();

        this.listenTo(this.genre_collection, 'update', this.render);
        this.listenTo(this.collection, 'update', this.render_list);

    },

    render: function() {
        console.log('render');

        this.$('#container').html(this.template({
            genres: this.genre_collection.models
        }));

        return this;
    },

    render_list: function() {
        console.log('render list');
        var html = this.template({
            genres: this.genre_collection.models,
            tracks: this.collection.models
        });
        console.log(html);
        var $selector = this.$('#tracklist');
        console.log($selector);
        $selector.replaceWith($(html));
        return this;
    },

    ////////////
    // events //
    ////////////
    onSearchClick: function() {
        console.log('search changed');
        this.collection.fetch({
            data: { limit: 30, type: 'search', keyword: $('#keyword').val() }
        });
    },

    onGenreChange: function() {
        console.log('genre changed');
        this.collection.fetch({
            data: { limit: 30, type: 'genre', genre_id: $('#genre_select').val() }
        });
    },
});
$('#pagetitle').html(_.template(Search_view_title_template));

_.template函数返回一个函数,该函数在调用时返回呈现的模板。

可能会与this.template混淆,后者通常包含_.template的结果,可以随时调用(this.template(data))。

拆分你的回调,功能便宜且不必要switch很难看。

我将search变为onGenreChangeonSearchClick

$('body').css('padding-top','124px');

尽量避免这种情况,可以使用CSS,甚至内联<style>标记或内联style=""属性轻松完成。如果你需要它与动态行为相关,那么在css文件中创建一个类(例如search-class),然后用jQuery切换类,将“设计”责任移出js:

$('body').toggleClass('search-class');
var that = this;

在处理回调中上下文(this)不同的回调时,这是唯一。在Backbone中,大多数情况下,它是可以避免的,因为context选项通常可用并且在大多数情况下自动设置(如events回调)。

this.$el.find(selector)

这相当于this.$(selector)。只是一个小捷径。

.replaceWith($(selector,html));

replaceWith需要 htmlString或Element或Array或jQuery

$(selector, html)期望选择器和上下文。您希望$(html)将您的html字符串转换为jQuery元素。