Backbone 模板
主干 SPA 模板由 Kazi Manzur Rashid 编写
Backbone.js SPA 模板旨在帮助你使用Backbone.js 快速构建交互式客户端 Web 应用 。
该模板提供了一个初始框架,用于在 ASP.NET MVC 中开发Backbone.js应用程序。 它现成提供基本的用户登录功能,包括用户注册、登录、密码重置和使用基本电子邮件模板进行用户确认。
要求:
创建主干模板项目
单击上面的“下载”按钮,下载并安装模板。 模板打包为 Visual Studio 扩展 (VSIX) 文件。 可能需要重启 Visual Studio。
在“ 模板 ”窗格中,选择“ 已安装的模板 ”,然后展开 “Visual C# ”节点。 在 “Visual C#”下,选择“ Web”。 在项目模板列表中,选择 “ASP.NET MVC 4 Web 应用程序”。 给该项目命名,然后单击“确定”。
在 “新建项目 ”向导中,选择“Backbone.js SPA 项目”。
按 Ctrl-F5 在不调试的情况下生成并运行应用程序,或按 F5 以通过调试运行。
单击“我的帐户”会显示登录页面:
演练:客户端代码
让我们从客户端开始。 客户端应用程序脚本位于 ~/Scripts/application 文件夹中。 该应用程序以 TypeScript (.ts 文件) 编写,这些文件) 编译为 JavaScript (.js 文件。
应用程序
Application
在 application.ts 中定义。 此对象初始化应用程序并充当根命名空间。 它维护跨应用程序共享的配置和状态信息,例如用户是否已登录。
方法 application.start
创建模式视图,并附加应用程序级事件的事件处理程序,例如用户登录。 接下来,它会创建默认路由器,并检查是否指定了任何客户端 URL。 否则,它会重定向到默认 URL (#!/) 。
事件
开发松散耦合组件时,事件始终很重要。 应用程序通常会执行多个操作来响应用户操作。 主干提供具有模型、集合和视图等组件的内置事件。 模板使用“发布/订阅”模型,而不是在这些组件之间创建相互依赖关系:在 events
events.ts 中定义的 对象充当用于发布和订阅应用程序事件的事件中心。 对象 events
是单一实例。 以下代码演示如何订阅事件,然后触发事件:
events.on('myEvent', (e: MyEventArg) => {
// Do your work
});
// Later in the code
events.trigger('myEvent', { arg: 'myValue' });
路由器
在Backbone.js中,路由器提供了路由客户端页面并将其连接到操作和事件的方法。 模板在 router.ts 中定义单个路由器。 路由器创建可激活的视图,并在切换视图时保持状态。 下一部分将介绍 (可激活视图。) 最初,该项目有两个虚拟视图,即“主页”和“关于”。 它还具有 NotFound 视图,如果路由未知,则会显示该视图。
视图
视图在 ~/Scripts/application/views 中定义。 有两种类型的视图:可激活视图和模式对话视图。 可激活的视图由路由器调用。 显示可激活视图时,所有其他可激活视图将变为非活动状态。 若要创建可激活的视图,请使用 对象扩展视图 Activable
:
export class MyView extends Backbone.View {
// Other implementation details
}
// Extending with Activable
_.extend(MyView.prototype, Activable);
使用 扩展 Activable
向视图添加两个新方法: activate
和 deactivate
。 路由器调用这些方法来激活视图并使视图非活动。
模式视图作为 Twitter Bootstrap 模式对话框实现。 Membership
和 Profile
视图是模式视图。 模型视图可由任何应用程序事件调用。 例如,在 Navigation
视图中,单击“我的帐户”链接会显示 Membership
视图或 Profile
视图,具体取决于用户是否已登录。 将 Navigation
单击事件处理程序附加到具有 data-command
属性的任何子元素。 下面是 HTML 标记:
<li>
<a href="#" data-command="myAccount">
<i class="icon-user"></i> My Account
</a>
</li>
下面是 navigation.ts 中用于挂接事件的代码:
export class Navigation extends Backbone.View {
// Other implementation details
handleCommand(e: JQueryEventObject) {
var command = $(e.currentTarget).attr('data-command');
if (command) {
events.trigger(command);
}
}
}
Navigation.prototype.events = () => {
return {
'click [data-command]': 'handleCommand'
};
};
模型
模型在 ~/Scripts/application/models 中定义。 这些模型都有三个基本内容:默认属性、验证规则和服务器端终结点。 下面是一个典型示例:
export class Session extends Backbone.Model {
urlRoot() {
return serverUrlPrefix + '/sessions'
}
defaults(): ISessionAttributes {
return {
email: null,
password: null,
rememberMe: false
}
}
validate(attributes: ISessionAttributes): IValidationResult {
var errors = {};
if (!attributes.email) {
Validation.addError(errors, 'email', 'Email is required.');
}
if (!attributes.password) {
Validation.addError(errors, 'password', 'Password is required.');
}
if (!_.isEmpty(errors)) {
return { errors: errors };
}
}
}
插件
~/Scripts/application/lib 文件夹包含一些方便的 jQuery 插件。form.ts 文件定义用于处理表单数据的插件。 通常需要序列化或反序列化表单数据并显示任何模型验证错误。 form.ts 插件具有 、 和 showFieldErrors
等serializeFields
deserializeFields
方法。 以下示例演示如何将窗体序列化为模型。
// Here $el is the form element
// Hide existing errors if there is any
this.$el.hideSummaryError().hideFieldErrors();
// Subscribe invalid event which
// is fired when validation fails
model.on('invalid', () =>
this.$el.showFieldErrors{(
errors: model.validationError.errors;
)}
);
model.save(this.$el.serializeFields(), {
success: () => { }, // lets do something good
error: (m, jqxhr: JQueryXHR) => {
if (jqxhr.status === 400) { // bad request
// Handle server side field errors
var response = <any>$.parseJSON(jqxhr.responseText);
if (response && _.has(response, 'ModelState')) {
return this.$el.showFieldErrors({
errors: response.ModelState
});
}
}
// All other server errors
this.$el.showSummaryError({
message: 'An unexpected error has occurred while performing ' +
'operation.'
});
}
});
flashbar.ts 插件向用户提供各种反馈消息。 方法为 $.showSuccessbar
、 $.showErrorbar
和 $.showInfobar
。 在后台,它使用 Twitter Bootstrap 警报来显示精美的动画消息。
confirm.ts 插件替换了浏览器的确认对话框,尽管 API 略有不同:
$.confirm({
prompt: 'Are you sure you want to do it?',
ok: => { //Do something useful },
cancel: => { // Do something else }
)};
演练:服务器代码
现在,让我们看看服务器端。
Controllers
在单页应用程序中,服务器在用户界面中仅扮演一个小角色。 通常,服务器呈现初始页,然后发送和接收 JSON 数据。
该模板有两个 MVC 控制器: HomeController
呈现初始页面,用于 SupportsController
确认新用户帐户和重置密码。 模板中的所有其他控制器都是 ASP.NET Web API控制器,用于发送和接收 JSON 数据。 默认情况下,控制器使用新 WebSecurity
类来执行与用户相关的任务。 但是,它们也有可选的构造函数,可用于为这些任务传入委托。 这使测试更容易,并允许使用 IoC 容器将 替换为 WebSecurity
其他内容。 以下是示例:
public class SessionsController : ApiController
{
private readonly Func<string, string, bool, bool> signIn;
private readonly Action signOut;
public SessionsController() : this(WebSecurity.Login, WebSecurity.Logout)
{
}
public SessionsController(
Func<string, string, bool, bool> signIn,
Action signOut)
{
this.signIn = signIn;
this.signOut = signOut;
}
// Rest of the code
}
视图
视图设计为模块化:页面的每个部分都有其自己的专用视图。 在单页应用程序中,通常包含没有任何相应控制器的视图。 可以通过调用 @Html.Partial('myView')
来包含视图,但这很繁琐。 为了简化此操作,模板定义了一个帮助程序方法 , IncludeClientViews
用于呈现指定文件夹中的所有视图:
@Html.IncludeClientViews('yourViewFolder')
如果未指定文件夹名称,则默认文件夹名称为“ClientViews”。 如果客户端视图也使用分部视图,请使用下划线字符 (命名分部视图, _SignUp
例如,) 。 方法 IncludeClientViews
排除其名称以下划线开头的任何视图。 若要在客户端视图中包括分部视图,请调用 Html.ClientView('SignUp')
而不是 Html.Partial('_SignUp')
。
发送Email
若要发送电子邮件,模板使用 邮政。 但是,Postal 是使用 IMailer
接口从代码的其余部分抽象出来的,因此可以轻松地将其替换为另一个实现。 电子邮件模板位于“视图/电子邮件”文件夹中。 发件人的电子邮件地址在 web.config 文件中 sender.email
的 appSettings 部分的键中指定。 此外,在web.config时 debug="true"
,应用程序不需要用户电子邮件确认,以加快开发速度。
GitHub
还可以在 GitHub 上找到Backbone.js SPA 模板。