视图的哪个功能首先执行?初始化还是渲染?
Which function of a view gets executed first? initialize or render?
我在下面的代码中插入了三个console.log
,来自教程Your First Backbone.js App。
我的问题是:为什么 console.log(this.el)
显示元素的 innerHtml 已经 "rendered" 但 console.log('render runs!')
消息在它之后打印?
View的哪个函数先执行?初始化还是渲染?
$(function(){
// Create a model for the services
var Service = Backbone.Model.extend({
// Will contain three attributes.
// These are their default values
defaults:{
title: 'My service',
price: 100,
checked: false
},
// Helper function for checking/unchecking a service
toggle: function(){
this.set('checked', !this.get('checked'));
}
});
// Create a collection of services
var ServiceList = Backbone.Collection.extend({
// Will hold objects of the Service model
model: Service,
// Return an array only with the checked services
getChecked: function(){
return this.where({checked:true});
}
});
// Prefill the collection with a number of services.
var services = new ServiceList([
new Service({ title: 'web development', price: 200}),
new Service({ title: 'web design', price: 250}),
new Service({ title: 'photography', price: 100}),
new Service({ title: 'coffee drinking', price: 10})
// Add more here
]);
// This view turns a Service model into HTML
var ServiceView = Backbone.View.extend({
tagName: 'div',
events:{
'click': 'toggleService'
},
initialize: function(){
// Set up event listeners. The change backbone event
// is raised when a property changes (like the checked field)
console.log(this);
console.log(this.el);
this.listenTo(this.model, 'change', this.render);
},
render: function(){
// Create the HTML
console.log("render runs!");
this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>');
this.$('input').prop('checked', this.model.get('checked'));
// Returning the object is a good practice
// that makes chaining possible
return this;
},
toggleService: function(){
this.model.toggle();
}
});
// The main view of the application
var App = Backbone.View.extend({
// Base the view on an existing element
el: $('#main'),
initialize: function(){
// Cache these selectors
this.total = $('#total span');
this.list = $('#services');
// Listen for the change event on the collection.
// This is equivalent to listening on every one of the
// service objects in the collection.
this.listenTo(services, 'change', this.render);
// Create views for every one of the services in the
// collection and add them to the page
services.each(function(service){
var view = new ServiceView({ model: service });
this.list.append(view.render().el);
}, this); // "this" is the context in the callback
},
render: function(){
// Calculate the total order amount by agregating
// the prices of only the checked elements
var total = 0;
_.each(services.getChecked(), function(elem){
total += elem.get('price');
});
// Update the total price
this.total.text('$'+total);
return this;
}
});
new App();
});
控制台输出如下:
child {cid: "view7", model: child, $el: init[1], el: div}
<div>
<input type="checkbox" value="1" name="web development"> web development
<span>0</span></div>
render runs!
initialize
总是首先被调用,因为它在默认的 Backbone 的视图构造函数中。
render
每当您手动调用它时都会调用它。
services.each(function(service) {
// ServiceView 'initialize' is called here.
var view = new ServiceView({ model: service });
// ServiceView 'render' is called here.
this.list.append(view.render().el);
}, this);
为什么控制台在渲染前显示 el
?
事实上,控制台不会在渲染前显示该元素,而是在您在控制台中查看时对其进行评估。
这是一个简单的例子:
var myObject = {};
console.log(myObject);
myObject.test = "value";
如果您不得不猜测,您会说记录了一个空对象,您不会完全错了。
小蓝!
说:
Object value at left was snapshotted when logged, value below was evaluated just now.
如"mu is too short"、
所述
the console contains live references and doesn't copy anything. So when you get to the console to look at this.el
, it shows you what this.el
is right now rather than what it was when console.log(this.el)
was evaluated.
我在下面的代码中插入了三个console.log
,来自教程Your First Backbone.js App。
我的问题是:为什么 console.log(this.el)
显示元素的 innerHtml 已经 "rendered" 但 console.log('render runs!')
消息在它之后打印?
View的哪个函数先执行?初始化还是渲染?
$(function(){
// Create a model for the services
var Service = Backbone.Model.extend({
// Will contain three attributes.
// These are their default values
defaults:{
title: 'My service',
price: 100,
checked: false
},
// Helper function for checking/unchecking a service
toggle: function(){
this.set('checked', !this.get('checked'));
}
});
// Create a collection of services
var ServiceList = Backbone.Collection.extend({
// Will hold objects of the Service model
model: Service,
// Return an array only with the checked services
getChecked: function(){
return this.where({checked:true});
}
});
// Prefill the collection with a number of services.
var services = new ServiceList([
new Service({ title: 'web development', price: 200}),
new Service({ title: 'web design', price: 250}),
new Service({ title: 'photography', price: 100}),
new Service({ title: 'coffee drinking', price: 10})
// Add more here
]);
// This view turns a Service model into HTML
var ServiceView = Backbone.View.extend({
tagName: 'div',
events:{
'click': 'toggleService'
},
initialize: function(){
// Set up event listeners. The change backbone event
// is raised when a property changes (like the checked field)
console.log(this);
console.log(this.el);
this.listenTo(this.model, 'change', this.render);
},
render: function(){
// Create the HTML
console.log("render runs!");
this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>');
this.$('input').prop('checked', this.model.get('checked'));
// Returning the object is a good practice
// that makes chaining possible
return this;
},
toggleService: function(){
this.model.toggle();
}
});
// The main view of the application
var App = Backbone.View.extend({
// Base the view on an existing element
el: $('#main'),
initialize: function(){
// Cache these selectors
this.total = $('#total span');
this.list = $('#services');
// Listen for the change event on the collection.
// This is equivalent to listening on every one of the
// service objects in the collection.
this.listenTo(services, 'change', this.render);
// Create views for every one of the services in the
// collection and add them to the page
services.each(function(service){
var view = new ServiceView({ model: service });
this.list.append(view.render().el);
}, this); // "this" is the context in the callback
},
render: function(){
// Calculate the total order amount by agregating
// the prices of only the checked elements
var total = 0;
_.each(services.getChecked(), function(elem){
total += elem.get('price');
});
// Update the total price
this.total.text('$'+total);
return this;
}
});
new App();
});
控制台输出如下:
child {cid: "view7", model: child, $el: init[1], el: div}
<div>
<input type="checkbox" value="1" name="web development"> web development
<span>0</span></div>
render runs!
initialize
总是首先被调用,因为它在默认的 Backbone 的视图构造函数中。
render
每当您手动调用它时都会调用它。
services.each(function(service) {
// ServiceView 'initialize' is called here.
var view = new ServiceView({ model: service });
// ServiceView 'render' is called here.
this.list.append(view.render().el);
}, this);
为什么控制台在渲染前显示 el
?
事实上,控制台不会在渲染前显示该元素,而是在您在控制台中查看时对其进行评估。
这是一个简单的例子:
var myObject = {};
console.log(myObject);
myObject.test = "value";
如果您不得不猜测,您会说记录了一个空对象,您不会完全错了。
小蓝!
说:
Object value at left was snapshotted when logged, value below was evaluated just now.
如"mu is too short"、
所述the console contains live references and doesn't copy anything. So when you get to the console to look at
this.el
, it shows you whatthis.el
is right now rather than what it was whenconsole.log(this.el)
was evaluated.