如何在更新集合时更新模板的一部分?
How to update part of a template when a collection is updated?
我试图在更新集合时仅更新 Backbone 视图使用的模板的一部分。下面的代码成功执行了 search()
和 render_list()
方法。此外,console.log(html)
显示完整模板的 html。但是当我执行 replaceWith
时,它会将选择器替换为空。如果我将 $(selector,html)
替换为字符串(即:'test'),它会成功替换为 'test'。
因此,出于某种原因,$(selector, html)
选择器没有按预期执行。更奇怪的是,浏览器请求更新的 html 选择器中的图像,即使更新的 html 的 none 被插入到文档中。
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() }
});
},
});
$('#pagetitle').html(_.template(Search_view_title_template));
_.template
函数 returns 一个函数,它本身 returns 调用时呈现的模板。
容易与this.template
混淆,后者通常包含_.template
的结果并准备调用(this.template(data)
)。
拆分你的回调,函数很便宜而且不必要switch
很丑。
我把你的search
变成了onGenreChange
和onSearchClick
。
$('body').css('padding-top','124px');
尽量避免这种情况,使用 CSS 甚至内联 <style>
标记或内联 style=""
属性可以轻松完成。如果您需要它,因为它与动态行为有关,请在 css 文件中创建一个 class(例如 search-class
),然后将 class 切换为 jQuery, 将 "design" 责任移出 js:
$('body').toggleClass('search-class');
var that = this;
只有在处理回调中上下文 (this
) 不同的回调时才需要。在 Backbone 中,大多数情况下,它是可以避免的,因为 context
选项通常可用并在大多数情况下自动设置(如 events
回调)。
this.$el.find(selector)
这等同于this.$(selector)
。只是一个小捷径。
.replaceWith($(selector,html));
replaceWith
需要一个 html 字符串或元素或数组或 jQuery.
$(selector, html)
需要 选择器和上下文 。您希望 $(html)
将 html 字符串转换为 jQuery 元素。
我试图在更新集合时仅更新 Backbone 视图使用的模板的一部分。下面的代码成功执行了 search()
和 render_list()
方法。此外,console.log(html)
显示完整模板的 html。但是当我执行 replaceWith
时,它会将选择器替换为空。如果我将 $(selector,html)
替换为字符串(即:'test'),它会成功替换为 'test'。
因此,出于某种原因,$(selector, html)
选择器没有按预期执行。更奇怪的是,浏览器请求更新的 html 选择器中的图像,即使更新的 html 的 none 被插入到文档中。
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() }
});
},
});
$('#pagetitle').html(_.template(Search_view_title_template));
_.template
函数 returns 一个函数,它本身 returns 调用时呈现的模板。
容易与this.template
混淆,后者通常包含_.template
的结果并准备调用(this.template(data)
)。
拆分你的回调,函数很便宜而且不必要switch
很丑。
我把你的search
变成了onGenreChange
和onSearchClick
。
$('body').css('padding-top','124px');
尽量避免这种情况,使用 CSS 甚至内联 <style>
标记或内联 style=""
属性可以轻松完成。如果您需要它,因为它与动态行为有关,请在 css 文件中创建一个 class(例如 search-class
),然后将 class 切换为 jQuery, 将 "design" 责任移出 js:
$('body').toggleClass('search-class');
var that = this;
只有在处理回调中上下文 (this
) 不同的回调时才需要。在 Backbone 中,大多数情况下,它是可以避免的,因为 context
选项通常可用并在大多数情况下自动设置(如 events
回调)。
this.$el.find(selector)
这等同于this.$(selector)
。只是一个小捷径。
.replaceWith($(selector,html));
replaceWith
需要一个 html 字符串或元素或数组或 jQuery.
$(selector, html)
需要 选择器和上下文 。您希望 $(html)
将 html 字符串转换为 jQuery 元素。