This chapter covers
- Improving selectors for better performance
- Organizing your code in modules
- Loading modules with RequireJS
- Managing dependencies with Bower
- Creating SPAs with Backbone.js
15.1 Improving the performance of your selectors
15.1.1 Avoiding the Universal selector
$('form :checkbox');
$('form input:checkbox');
$('input:checkbox', 'form'); v
$('form > *');
$('form').children(); v
15.1.2 Improving the Class selector
var $elements = $('p.description'); v
15.1.3 Don't abuse the context parameter
var $element = $('#test', 'div');
var $element = $('#test'); v
15.1.4 Optimizing filters
$('p:visible');
$('p').filter(':visible'); v
$(':reset');
$('[type="reset"]');
$('input[type="reset"]'); v
$('#my-list li').slice(0,2); v
$('#my-list li:lt(2)');
$('input[placeholder!="Name"]');
$('input').not('[placeholder="Name"]'); v
15.1.5 Don't overspecify selectors
var $value = $('.revenue span.value'); v
var $value = $('table.revenue .value');
var $values = $('table.revenue tr td span.value');
var $values = $('.revenue span.value'); v
15.2 Organizing your code into modules
15.2.1 The object literals pattern
var myService = {
foo: function() {},
bar: function() {},
baz: function() {},
obj: {},
anotherObj: {}
}
var myService = {
foo: function() {},
payment: {
obj: {},
bar: function() {}
},
basket: {
anotherObj: {},
baz: function() {}
}
};
myService.basket.baz();
15.2.2 The Module pattern
var myFirstModule = (function() {
return {
foo: function() {},
bar: function () {},
obj: {}
}
})();
var myFirstModule = (function() {
var count = 0;
function doSomethingPrivate() {};
return {
obj: {},
foo: function() { count++; },
bar: function () { doSomethingPrivate(); }
}
})();
window.myService = (function(oldMyService) {
oldMyService.basket = {
baz: function() {},
anotherObj: {}
};
return oldMyService;
})(window.myService || {});
15.3 Loading modules with RequireJS
15.3.1 Getting started with RequireJS
define([[id, ] dependencies,] factory)
Parameters
id (String)
dependencies (Array)
factory (Object|Function)
Returns
undefined
define(['Person'], function(Person) {
function Car() {
this.getOwner = function() {
return 'The owner is ' + Person.name;
};
}
return Car;
});
require(['Car'], function(Car) {
var car = new Car();
alert(car.getOwner());
});
15.3.2 Using RequireJS with jQuery
define(['jquery'], function($) {
$.fn.jqia = function() {
//Plugin code here...
}
});
15.4 Managing dependencies with Bower
15.4.1 Getting started with Bower
15.4.2 Searching a package
15.4.3 Installing,updating, and deleting packages
15.5 Creating single-page applications with Backbone.js
15.5.1 Why use an MV* framework?
15.5.2 Starting with Backbone.js
MODEL
var todo = Backbone.Model.extend({
position: 1,
title: '',
done: false
});
COLLECTION
var todoList = Backbone.Collection.extend({
model: todo
});
VIEW
var TodoView = Backbone.View.extend({
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var TodoView = Backbone.View.extend({
tagName: 'li',
className; 'todo',
template: _.template($('#todo-template').html())
});
ROUTER
var TodoRouter = Backbone.Router.extend({
routes: {
"todo/:id": "getTodo",
"search/:string": "searchTodo"
},
getTodo: function(id) {
// Your code here
},
searchTodo(string) {
// Your code here
}
});
15.5.3 Creating a Todos manage application using Backbone.js
CREATING THE HTML
INSTALLING BACKBONE.JS
THE TODO MODEL
app.Todo = Backbone.Model.extend({
defaults: {
position: 1,
title: '',
done: false
},
initialize: function() {
this
.on('invalid', function(model, error) {
console.log(error);
})
.on('add', function(model, error) {
console.log(
'Todo with title "' + model.get('title') + '" added.'
);
})
.on('remove', function(model, error) {
console.log(
'Todo with title "' + model.get('title') + '" deleted.'
);
})
.on('change', function(model, error) {
console.log(
'Todo with title "' + model.get('title') + '" updated.'
);
});
},
validate: function(attributes) {
if(!attributes.title) {
return 'Title is required and cannot be empty';
}
if(
attributes.position === undefined ||
parseInt(attributes.position, 10) < 1
) {
return 'Position must be positive';
}
}
});
THE TODOS COLLECTION
app.todoList = new (Backbone.Collection.extend({
model: app.Todo,
localStorage: new Backbone.LocalStorage('todo-list'),
comparator: 'position',
initialize: function() {
this.on('add remove', this.collectionChanged);
},
collectionChanged: function(todo) {
if (todo.isValid()) {
this.each(function(element, index) {
element.save({
position: index + 1
});
});
this.sort();
}
}
}));
THE TODO VIEWS
app.TodoView = Backbone.View.extend({
tagName: 'li',
className: 'todo',
template: _.template($('#todo-template').html()),
events: {
'blur .todo-position': 'updateTodo',
'change .todo-done': 'updateTodo',
'keypress .todo-title': 'updateOnEnter',
'click .todo-delete': 'deleteTodo'
},
initialize: function() {
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'destroy', this.remove);
},
deleteTodo: function() {
this.model.destroy();
},
updateTodo: function() {
this.model.save({
title: $.trim(this.$title.text()),
position: parseInt(this.$position.text(), 10),
done: this.$done.is(':checked')
});
},
updateOnEnter: function(event) {
if (event.which === 13) {
this.updateTodo();
}
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
this.$title = this.$('.todo-title');
this.$position = this.$('.todo-position');
this.$done = this.$('.todo-done');
return this;
}
});
THE APPLICATION VIEW
app.appView = Backbone.View.extend({
el: '#todo-sheet',
events: {
'click #new-todo-save': 'createTodo'
},
initialize: function() {
this.$input = this.$('#new-todo');
this.$list = this.$('ul.todos');
this.listenTo(app.todoList, 'reset sort destroy', this.showTodos);
this.listenTo(app.todoList, 'invalid', this.showError);
app.todoList.fetch();
},
createTodo: function() {
app.todoList.create(
{
title: this.$input.val().trim()
},
{
at: 0,
validate: true
}
);
this.$input.val('');
},
showError: function(collection, error, model) {
this
.$('.error-message')
.finish()
.html(error)
.fadeIn('slow')
.delay(2000)
.fadeOut('slow');
},
showTodo: function(todo) {
if (todo.isValid()) {
var view = new app.TodoView({ model: todo });
this.$list.prepend(view.render().el);
}
},
showTodos: function() {
this.$list.empty();
var todos = app.todoList.sortBy(function(element) {
return -1 * parseInt(element.get('position'), 10);
});
for(var i = 0; i < todos.length; i++) {
this.showTodo(todos[i]);
}
}
});
15.6 Summary
selecting elements
RequireJS
Bower
Backbone.js
15.7 The end
We also wish you health and happiness, and may all your bugs be easily solvable!
网友评论