Spine 学习笔记 – 1
//总结: 将事件处理函数代理到类内部~~
Class.proxy = function(func){
var that = this;
return function(){
arguments[0].element = this;
func.apply(that,arguments);
}
}
以下翻译自: http://maccman.github.com/spine/
Spine
Spine 是一个用于构建JavaScript应用程序的轻量级框架。Spine 提供给开发者一个单纯的MVC结构,使得开发者能够集中精力到应用的实际开发中,构建优秀的Web应用程序。
Spine 给人的第一印象与另外一款框架 Backbone 很相似,但它其实有自己非常独特的一面。
Spine 非常小,大约500行代码,在经过minify和gz之后大约只有2K。虽然很小,但是使用得当,Spine的功能会十分给力。
最新版:https://github.com/maccman/spine/raw/master/spine.js (minified).
概述
Spine 到底有哪些优点能够让它从众多的框架中脱颖而出?
- 类的实现采用真真的原型继承(prototypal inheritance)方式
- 基于Backbone的API 实现轻量级的controller
- 完整的Model层和ORM支持
- 继承HTML本地存储适配器和Ajax功能
- 支持异步的服务器通讯
- 轻量而简单
当然,仅从这里无法看到实际的效果,你可以参考下面的例子,自己决定。
例子
Spine 包含很多NB的范例,这些范例演示了Spine 很多功能,能帮助你更好的理解这个框架。Spine 是夸浏览器的,可是一些例子可能因为CSS的原因在IE等其他浏览器中可能会很难看。
Todos 实施一个非常简单的 任务 应用程序,用户可以CRUD所有的任务,也可以将任务标记为 已完成,源代码位于:GitHub

Spine contacts是一个简单的通讯录,允许用户CRUD联系人,源代码位于:GitHub

Holla 是一个实时聊天应用程序,结合了Rails,Juggernaut和Spine,相对其他例子来讲功能较为丰富,源代码位于:GitHub

安装
使用Spine非常简单,直接在页面中引用该文件即可:
Spine 没有任何依赖,同时针对jQuery和Zepto两款JS框架做了优化,从而可以更好的结合应用。部分功能,如Ajax和HtmL5本地存储需要加载额外的文件(位于lib文件夹内)。
类
Spine中的类设计很特别,Spine使用原声的 原型继承 方式进行,而不是进行属性的复制。下面的代码演示了这种类继承的使用方法。
类的创建
var Task = Spine.Class.create();
create() 函数接收两个可选的参数,用来提供实例属性和类属性(属性:可以使变量或函数)。
Spine.Class.create([instanceProperties, classProperties]);
var User = Spine.Class.create({
name: "Carolin"
});
另外,你也可以通过 include() 函数增加实例属性,extend() 函数怎家类属性:
var User = Spine.Class.create();
User.extend({
find: function(){ /* ... */ }
});
User.include({
name: "Tonje"
});
由于Spine不适用构造函数,所以实例化一个类对象需要使用 inst() 函数:
var User = Spine.Class.create({
name: "Tonje"
});
var user = User.inst();
assertEqual( user.name, "Tonje" );
user.name = "Trish";
assertEqual( user.name, "Trish" );
所有传递给 inst() 函数的参数都会被传递给类的初始化函数 init():
var User = Spine.Class.create({
init: function(name){
this.name = name;
}
});
User.inst("Martina");
assertEqual( user.name, "Martina" );
子类可以藉由父类的 create() 函数创建,父类所有属性都将被子类继承:
var Friend = User.create();
var friend = Friend.inst("Tim");
assertEqual( friend.name, "Tim" );
因为使用了原型继承方式(所有属性解析都发生在运行时),所以在运行时对父类的属性变更,会立刻显示在子类中:
var User = Super.Class.create();
var Friend = User.create();
User.include({defaultName: "(empty)"});
assertEqual( Friend.inst().defaultName, "(empty)" );
上下文
由于在javascript中上下文经常变更,如何能保证运行上下文就显得尤其重要。一般在使用 事件侦听函数 调用时使用了另外的上下文(Window或对应元素)。Spine提供了一些函数来解决这个问题。
你可把函数传递个 proxy() 来保证调用使用原上下文:
var Tasks = Spine.Class.create({
init: function(){
$("#destroy").click(this.proxy(this.destroy));
},
destroy: function(){ /* ... */ }
});
同时,你也可以调用 proxyAll() 来对指定函数的后续调用做一次性 proxy():
var Tasks = Spine.Class.create({
init: function(){
this.proxyAll("destroy")
$("#destroy").click(this.destroy);
},
destroy: function(){ /* ... */ }
});
事件
Spine 使用 Spine.Events 来为类添加事件支持,使用很简单,为该类添加(include()/extend())该模块即可:
var Tasks = Spine.Class.create(); Tasks.extend(Spine.Events);
Spine.Events 提供了三个方法 bind() unbind() trigger(),这三个方法与jQuery中响应方法的使用方式几乎相同(name,callback):(你也可以一次性绑定多个事件)
Tasks.bind("create", function(){ /* ... */ });
Tasks.trigger("create", ["some", "data"]);
Tasks.bind("create update destroy", function(){ this.trigger("change") });
回调函数调用的上下文保持不变(该事件的上下文)。 在trigger()函数传递的参数会被进一步传送给回调函数:Tasks.bind("create", function(name){ alert(name); }); Tasks.trigger("create", "Take out the rubbish");模型
模型 是Spine的核心内容,也是应用程序的核心内容。模型层应该与应用程序的其他部分独立开来,其数据存储在 Model.records中。
模型的创建使用 setup() 函数(非create()),该函数接受一个字符串作为模型名称,一个数组作为模型记录的属性列名称。Model 在Spine中通用是一个类,所以可以使用类所有相关方法:
var Contact = Spine.Model.setup("Contact", ["first_name", "last_name"]);
Contact.include({
fullName: function(){
return(this.first_name + " " + this.last_name);
}
});
模型实例的创建同样使用 inst() 函数进行:
var contact = Contact.inst({first_name: "Alex", last_name: "MacCaw"});
assertEqual( contact.fullName(), "Alex MacCaw"
fastcgi_finish_request Nginx模块开发入门
很强大的东西。希望多分享。