【转】Backbone标准例子——通讯录

时间:2023-03-09 07:46:20
【转】Backbone标准例子——通讯录

参考:http://z2009zxiaolong.iteye.com/blog/1847833

感觉不错的例子,模型、视图、路由等知识点都用到了:),将此文中的源码转载如下:

http://dmyz.org/archives/598 这篇教程也不错,讲的很清楚。

//------------------------------------------------------------------------------------

backbone.js源码初略:

backbone.js相当轻量级,以其0.5.1 版本为例,总代码不过1100行左右。主要代码包括:

event:定义一个event和callback的list,实现时间的增、删即回调;

async:封装http的post\delete\get\update方法;

model:定义数据模型对象,主要是其属性(比如url)以及关键的回调,比如fetch会调用async模块的ajax方法获取数据,并执行回调;

collection:是model的集合,在这个集合中实现了一堆方法的扩展接口,例如foreach,each,map等等;

route:定义一个route列表,操作时会相应操作history对象,实现历史跳转;

view:对应视图,主要是获取其中的DOM组件并渲染,同时处理绑定在view上的事件;

//-------------------------------------------------------------------------------------

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Backbone通讯录</title>
<link rel="stylesheet" href="css/application.css" type="text/css" charset="utf-8">
</head>
<body>
<header id="header"><h1>Backbone通讯录</h1></header>
<article id="article"></article>
</body>
<script src="js/lib/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="js/lib/underscore.js" type="text/javascript" charset="utf-8"></script>
<script src="js/lib/backbone.js" type="text/javascript" charset="utf-8"></script>
<script src="js/lib/backbone-localstorage.js" type="text/javascript" charset="utf-8"></script>
<script src="js/application.js" type="text/javascript" charset="utf-8"></script> <!-- 联系人 -->
<script type="text/template" id="tpl-item">
<%= (name ? name : "<i>无名</i>") %>
</script> <!-- 左边的侧边条,包括联系人列表 -->
<script type="text/template" id="tpl-sidebar">
<header>
<input type="search" placeholder="搜索" results="0" incremental="true" autofocus>
</header>
<div class="items"></div>
<footer>
<button>新建联系人</button>
</footer>
</script> <!-- 显示联系人详细信息 -->
<script type="text/template" id="tpl-show">
<header>
<a class="edit">编辑</a>
</header>
<div class="content">
<p><label>姓名:<%= name %></label></p>
<p><label>邮箱:<%= email %></label></p>
</div>
</script> <!-- 编辑联系人信息 -->
<script type="text/template" id="tpl-edit">
<header>
<a class="save">保存</a>
<a class="delete">删除</a>
</header>
<div class="content">
<form>
<label>
<span>姓名:</span>
<input type="text" name="name" value="<%= name %>">
</label>
<label>
<span>邮箱:</span>
<input type="email" name="email" value="<%= email %>">
</label>
<button>保存</button>
</form>
</div>
</script>
</html>
(function($) {
$(document).ready(function() {
var Contact = Backbone.Model.extend({
defaults: {
name: '',
email: ''
}, validate: function(attrs, options) {
if (attrs.name == "") {
return "用户名不能为空!";
};
}, // 用户搜索的辅助方法
filter: function(query) {
if (typeof(query) === 'undefined' || query === null || query === '') return true;
query = query.toLowerCase();
return this.get('name').toLowerCase().indexOf(query) != -1 || this.get('email').toLowerCase().indexOf(query) != -1;
}
}); var Contacts = Backbone.Collection.extend({
model: Contact,
localStorage: new Store('my-contacts')
}); // 单个联系人视图
var ContactItemView = Backbone.View.extend({
className: 'item',
template: _.template($('#tpl-item').html()),
events: {
'click': 'select'
}, initialize: function() {
_.bindAll(this, 'select');
this.model.bind('reset', this.render, this);
this.model.bind('change', this.render, this);
this.model.bind('destroy', this.remove, this);
if (this.model.view) this.model.view.remove();
this.model.view = this;
}, // 渲染联系人
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}, select: function() {
appRouter.navigate('contacts/' + this.model.cid, {
trigger: true
});
}, active: function() {
this.$el.addClass('active');
}, deactive: function() {
this.$el.removeClass('active');
}
}); // 左边的侧边条视图
var SidebarView = Backbone.View.extend({
className: 'sidebar',
template: _.template($('#tpl-sidebar').html()),
events: {
'click footer button': 'create',
'click input': 'filter',
'keyup input': 'filter'
}, initialize: function() {
_.bindAll(this, 'create', 'filter');
this.model.bind('reset', this.renderAll, this);
this.model.bind('add', this.add, this);
this.model.bind('remove', this.remove, this);
}, // 渲染联系人列表
render: function() {
$(this.el).html(this.template());
this.renderAll();
return this;
}, renderAll: function() {
this.$(".items").empty();
this.model.each(this.renderOne, this);
this.filter();
}, renderOne: function(contact) {
var view = new ContactItemView({
model: contact
});
this.$(".items").append(view.render().el);
}, create: function() {
var contact = new Contact();
this.model.add(contact);
appRouter.navigate('contacts/' + contact.cid + '/edit', {
trigger: true
});
}, filter: function() {
var query = $('input', this.el).val();
this.model.each(function(contact, element, index, list) {
contact.view.$el.toggle(contact.filter(query));
});
// this.model.last().view.$el.trigger("click")
}, active: function(item) {
if (this.activeItem) this.activeItem.view.deactive();
this.activeItem = item;
if (this.activeItem) this.activeItem.view.active();
}, add: function(contact) {
this.renderOne(contact);
}, remove: function(contact) {
console.log(contact);
}
});
// 显示选择的联系人详细信息
var ShowView = Backbone.View.extend({
className: 'show',
template: _.template($('#tpl-show').html()), events: {
'click .edit': 'edit'
}, initialize: function() {
_.bindAll(this, 'edit');
}, render: function() {
if (this.item) this.$el.html(this.template(this.item.toJSON()));
return this;
}, change: function(item) {
this.item = item;
this.render();
}, edit: function() {
if (this.item) appRouter.navigate('contacts/' + this.item.cid + '/edit', {
trigger: true
});
}
}); // 编辑选择的联系人
var EditView = Backbone.View.extend({
className: 'edit',
template: _.template($('#tpl-edit').html()), events: {
'submit form': 'submit',
'click .save': 'submit',
'click .delete': 'remove'
}, initialize: function() {
_.bindAll(this, 'submit', 'remove');
}, render: function() {
if (this.item) this.$el.html(this.template(this.item.toJSON()));
return this;
}, change: function(item) {
this.item = item;
this.render();
}, submit: function() {
this.item.set(this.form());
this.item.save();
appRouter.navigate('contacts/' + this.item.cid, {
trigger: true
});
return false;
}, form: function() {
return {
name: this.$('form [name="name"]').val(),
email: this.$('form [name="email"]').val()
};
}, remove: function() {
this.item.destroy();
this.item = null;
appRouter.navigate('', {
trigger: true
});
}
}); // 主视图,显示和编辑联系人
var MainView = Backbone.View.extend({
className: 'main stack',
initialize: function() {
this.editView = new EditView();
this.showView = new ShowView();
}, render: function() {
this.$el.append(this.showView.render().el);
this.$el.append(this.editView.render().el);
return this;
}, edit: function(item) {
this.showView.$el.removeClass('active');
this.editView.$el.addClass('active');
this.editView.change(item);
}, show: function(item) {
this.editView.$el.removeClass('active');
this.showView.$el.addClass('active');
this.showView.change(item);
}
}); // 整个页面的视图,管理SiderbarView和MainView两个子视图
var AppView = Backbone.View.extend({
className: 'contacts', initialize: function() {
this.sidebar = new SidebarView({
model: this.model
});
this.main = new MainView();
this.vdiv = $('<div />').addClass('vdivide');
this.model.fetch();
this.render();
}, render: function() {
this.$el.append(this.sidebar.render().el);
this.$el.append(this.vdiv);
this.$el.append(this.main.render().el);
$('#article').append(this.el);
return this;
}, show: function(item) {
this.sidebar.active(item);
this.main.show(item);
}, edit: function(item) {
this.sidebar.active(item);
this.main.edit(item);
}
}); // 路由
var AppRouter = Backbone.Router.extend({
routes: {
'': 'show',
'contacts/:id': 'show',
'contacts/:id/edit': 'edit'
}, show: function(id) {
if (id != undefined) {
appView.show(this.getContact(id));
} else {
appView.show(contacts.first());
}
}, edit: function(id) {
appView.edit(this.getContact(id));
}, getContact: function(id) {
return contacts.getByCid(id);
}
}); var contacts = new Contacts();
window.appView = new AppView({
model: contacts
});
window.appRouter = new AppRouter();
Backbone.history.start();
});
})(jQuery);