在传统的Web应用中,服务器端占据了主导地位,浏览器和服务器之间的流量非常密集,使用GET、POST请求(在Web表单中,还有可怕的回传)是常态。然而,越来越多的Web应用开始采用一种新的范式——单页应用(SPA)。Facebook和Gmail就是SPA的典型例子。SPA的核心概念是为用户提供更好、更响应、更无缝的体验,这样用户就很少需要离开浏览器,从而避免了长时间的全页面刷新往返服务器。Angular等框架提供了非常强大的方法来创建SPA,但如果没时间学习曲线,或者想要一些轻量级且简单的解决方案,像SammyJS这样的专注于路由的库是一个非常有用的选择。本文将介绍使用SPA路由的好处,并解释如何使用SammyJS快速构建一个清晰、可扩展、模块化的单页应用。
让考虑一个基于Web的地址簿。它将具有非常基础的功能:列出地址、搜索地址功能、创建/编辑/删除地址条目。即使这些功能受限,但它们仍然需要合理的数据输入和管理开销。在单页应用中,常见的工作流程方法是使用JavaScript按钮点击来推动事情的发展。这种方法鼓励使用全局变量来跟踪选定的当前数据记录的ID或状态。虽然这种方法在一定程度上是可行的,但它很快就会变得混乱。如果能够解决这个工作流程问题,就有清晰的关注点分离的基础,这将允许一个更清晰、可扩展和更易于维护的解决方案。
SammyJS被描述为“RESTful,事件驱动的JavaScript”。它允许以MVC的方式工作,但这是在客户端。就像在MVC和Web-API中有控制器可以接受GET/POST/DELETE等动词一样,也可以在SammyJS中实现这些模式。在传统的Web服务器中,使用完整的路由来访问控制器,而SammyJS路由则使用锚标签“#”来连接路由——可以在下面的例子中看到,它使用标准的“GET”动词从“#home”路由请求数据。
要让SammyJS运行起来,需要初始化它,并添加一些路由。
var app = $.sammy(function() {
this.get('#home', function() {
// 显示首页屏幕
});
this.get('#address/create', function() {
// 显示创建新地址屏幕
});
}).run('#home');
在上面的代码中,初始化了库,并使用“run”方法同时激活它,给出了默认路由“#home”。现在有两个路由,一个为用户提供首页,另一个显示创建新地址屏幕。两者都使用简单的GET动词。本文的目标是让快速上手SammyJS作为路由解决方案,用于MVC应用,所以将现在运行常见的用例场景以及它们是如何工作的——将避免构建一个完整的应用程序,无论多么琐碎。
为了演示目的,创建了一些DIV,它们将作为显示表单/区域,根据用户选择的路由显示/隐藏。这些可以被分离到单独的cshtml文件中,并使用HTML.Partial(..)进行渲染。
This is the Home div
当然,路由必须从某个地方调用——有一个基本的菜单结构,展示了不同的用例。
Home |
Show Div 1 |
Show Div with param |
Re-direct to div 1 |
Get div content from server
还有一个简单的HTML表单,将用于演示发布表单数据。
前两个示例路由非常基础,它们根据路由指令向用户显示/隐藏不同的DIV。
this.get('#home', function() {
hideAll();
$('#divHome').fadeIn();
});
this.get('#d1', function() {
hideAll();
$('#div1').fadeIn();
$('#div1_SomeLabel').text('');
});
有时希望将用户从一个路由发送到另一个路由——这就是重定向方法的用武之地。
this.get('#d4', function() {
hideAll();
this.redirect('#d1');
$('#div1_SomeLabel').text('Redirect from some a-tag');
});
下一个示例展示了如何从发送的查询字符串中获取值——首先,这里是调用路由的HTML。
Show Div with param
注意参数“id”和值“1234”。使用“params”在路由中访问查询名称和值。注意路由模式中的占位符“:”和被访问的“params”值。
this.get('#d2/:id', function() {
hideAll();
var tempID = this.params['id'];
$('#div2').fadeIn();
$('#div2_ParamVal').text(tempID)
});
处理表单的操作方式类似。声明表单(注意方法和动作路由)。
this.post('#/post/form', function() {
alert('here with ' + this.params['some_name'] + '\n\nNow hiding the form!');
$('#simpleForm').hide();
return false; // stops the default POST behaviour back to server
});
创建一个单页应用有很多挑战,包括内存管理、与服务器的数据交换等。这里有一个小型示例,展示了如何获取一个全新的、更新的服务器端部分页面,并使用它来更新用户的界面。
Sammy路由。
this.get('#GetRemote', function() {
hideAll();
GetRemoteDiv();
});
Ajax调用获取远程HTML以替换页面内容。
var GetRemoteDiv = function() {
$.ajax({
method: 'get',
url: '/home/LoadDivFromRemote'
}).done(function(dataRcvd) {
$('#divContent').empty();
$('#divContent').show();
$('#divContent').html(dataRcvd);
});
}
服务器端C#代码生成动态页面数据。
public ActionResult LoadDivFromRemote() {
ViewBag.Title = "Remotly injected!";
ViewBag.Message = "This div was remotly injected into the dom from the server at: " + DateTime.Now.ToLongTimeString();
return PartialView("~/Views/Home/RemoteDiv.cshtml");
}
HTML。
@ViewBag.Title
@ViewBag.Message
本文专注于路由的核心概念——如何使用路由是另一回事——建议通过SammyJS网站上的“JSON Store”示例(第一部分,第二部分)来深入理解这个库的能力。SammyJS附带了一系列非常有用的插件,涵盖了HTML模板、客户端本地存储、SPA谷歌分析助手等主题。强烈建议下载示例代码并尝试SammyJS。