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

Javascript 更新集合时如何更新模板的一部分?,javascript,jquery,html,backbone.js,Javascript,Jquery,Html,Backbone.js,我试图在更新集合时仅更新主干视图使用的模板的一部分。下面的代码成功地执行了search()和render\u list()方法。此外,console.log(html)显示完整模板的html。但是当我执行replaceWith时,它将选择器替换为空。如果我用字符串(即:“test”)替换$(选择器,html),它将成功地替换为“test” 因此,出于某种原因,$(选择器,html)选择器没有完成它的本意。更奇怪的是,即使没有更新的html插入到文档中,浏览器也会请求更新的html选择器中的图像

我试图在更新集合时仅更新主干视图使用的模板的一部分。下面的代码成功地执行了
search()
render\u list()
方法。此外,
console.log(html)
显示完整模板的html。但是当我执行
replaceWith
时,它将选择器替换为空。如果我用字符串(即:“test”)替换
$(选择器,html)
,它将成功地替换为“test”

因此,出于某种原因,
$(选择器,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;

});

没有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() }
        });
    },
});

该函数返回一个函数,调用该函数时,该函数本身将返回呈现的模板

它可能与
此.template
相混淆,后者通常包含
\uu.template
的结果,并且可以随时调用(
此.template(数据)


拆分回调,函数很便宜,不必要的
switch
很难看

我将您的
搜索
放入
onGenreChange
搜索点击


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

$('body').toggleClass('search-class');

只有在处理回调中上下文(
This
)不同的回调时,这才是必需的。在主干网中,大多数情况下是可以避免的,因为
上下文
选项通常可用,并且在大多数情况下都会自动设置(如
事件
回调)


这相当于
This.$(选择器)
。只是一点捷径


需要htmlString、元素、数组或jQuery

需要一个选择器和一个上下文。您希望
$(html)
将html字符串转换为jQuery元素

$('body').css('padding-top','124px');
$('body').toggleClass('search-class');
var that = this;
this.$el.find(selector)
.replaceWith($(selector,html));