为《基于 MVC 的 Javascript Web 富应用开发》填坑

  1. 1. contacts.js

《基于 MVC 的 Javascript Web 富应用开发》一书出版于2012年五月,作者基于自己写的 spine.js 框架讲解了 MVC JS 框架从无到有的构建方法。然后讲解了一个基于 spine.js 的联系人管理应用,一年之后,spine.js 已经愈加复杂和成熟,坑的地方来了,新的spine.js对旧代码的兼容性几乎为零。

init() 不能实例化类了,proxied 和 proxyAll 没有了,说好的 this.App 也木有了。。。

我们当然可以在 https://github.com/maccman/spine.contacts/tree/js 找到当时的spine.js,但是如果不兼容最新的版本,学了还是无以致用。于是笔者蛋痛地一点一点修正了代码不兼容的地方。算是为作者和后来人填了个天坑。

基于 MVC 的 Javascript Web 富应用开发 联系人管理应用

contacts.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 联系人模型
var Contact = Spine.Model.setup("Contact", ["first_name", "last_name", "email"]);
Contact.extend(Spine.Model.Local);
Contact.include({
truefullName: function() {
truetrueif (!this.first_name && !this.last_name) return;
truetruereturn(this.last_name);
true},
});
// 侧边栏控制器
$(function($) {
truewindow.Sidebar = Spine.Controller.create({
truetrueelements: {
truetruetrue".items": "items",
truetrue},
truetrueevents: {
truetruetrue"click button": "create",
truetrue},
truetruetemplate: function(items) {
truetruetruereturn($("#contactsTemplate").tmpl(items));
truetrue},
truetrueinit: function() {
truetruetruethis.list = new Spine.List({
truetruetruetrueel: this.items,
truetruetruetruetemplate: this.template,
truetruetrue});
truetruetruethis.list.bind("change", this.proxy(function(item) {
truetruetruetrueSpine.trigger('show:contact', item);
truetruetrue}));
truetruetrueSpine.bind("show:contact edit:contact", this.proxy(this.list.change));
truetruetrueContact.bind("refresh change", this.proxy(this.render));
truetrue},
truetruerender: function() {
truetruetruevar items = Contact.all();
truetruetruethis.list.render(items);
truetrue},
truetruecreate: function() {
truetruetruevar item = Contact.create();
truetruetrueconsole.log(item);
truetruetrueSpine.trigger("edit:contact", item);
truetrue},
true});
});
// 联系人控制器
$(function($) {
truewindow.Contacts = Spine.Controller.create({
truetrueelements: {
truetruetrue".show": "showEl",
truetruetrue".edit": "editEl",
truetruetrue".show .content": "showContent",
truetruetrue".edit .content": "editContent",
truetrue},
truetrueevents: {
truetruetrue"click .optEdit": "edit",
truetruetrue"click .optDestroy": "destroy",
truetruetrue"click .optSave": "save",
truetrue},
truetrueinit: function() {
truetruetruethis.show();
truetruetrueContact.bind("change", this.proxy(this.render));
truetruetrueSpine.bind("show:contact", this.proxy(this.show));
truetruetrueSpine.bind("edit:contact", this.proxy(this.edit));
truetrue},
truetruechange: function(item) {
truetruetruethis.current = item;
truetruetruethis.render();
truetrue},
truetruerender: function() {
truetruetruethis.showContent.html($("#contactTemplate").tmpl(this.current));
truetruetruethis.editContent.html($("#editContactTemplate").tmpl(this.current));
truetrue},
truetrueshow: function(item) {
truetruetrueif (item && item.id) this.proxy(this.change(item));
truetruetruethis.showEl.show();
truetruetruethis.editEl.hide();
truetrue},
truetrue// 当点击edit时调用
truetrueedit: function(item) {
truetruetrueconsole.log(item);
truetruetrueif (item && item.id) this.proxy(this.change(item));
truetruetruethis.showEl.hide();
truetruetruethis.editEl.show();
truetrue},
truetruedestroy: function() {
truetruetruethis.current.destroy();
truetrue},
truetruesave: function() {
truetruetruevar atts = this.editEl.serializeForm();
truetruetruethis.current.updateAttributes(atts);
truetruetruethis.show();
truetrue}
true});
});
// 应用程序控制器
$(function($) {
truewindow.App = Spine.Controller.create({
truetrueel: $("body"),
truetrueelements: {
truetruetrue".sidebar": "sidebarEl",
truetruetrue".contacts": "contactsEl",
truetrue},
truetrueinit: function() {
truetruetruethis.sidebar = new Sidebar({el: this.sidebarEl});
truetruetruethis.contact = new Contacts({el: this.contactsEl});
truetruetrueContact.fetch();
truetrue},
true});
truenew App();
});