集成 Knockout、JSRender 和 Twitter Bootstrap 与 MVC4





4.00/5 (2投票s)
如何在 MVC4 中将 JSRender 模板与 knockout.js 一起使用
引言
MVC 框架 毫无疑问地 改变了我们现在编写 Web 应用程序的方式,实现了表示层、数据和逻辑的清晰分离。
通过 HTML5/CSS3 和 jQuery,我们可以看到客户端实现的显著转变。
JSRender 和 Knockout 等新库为客户端代码带来了更多的关注点分离。
在这篇简短的文章中,我想展示一个关于我如何实现 MVC4、JSRender 和 Knockout 集成的示例。
背景
此代码主要用于展示客户端技术,以解耦您的数据与视图。我只会使用控制器来模拟从存储库检索数据。
准备您的解决方案
- 创建一个新的 MVC 4 应用程序
- 使用 NuGet 添加以下程序包
- jQuery
- Knockout
- Autofac
- Twitter Bootstrap
- 从 https://github.com/BorisMoore/jsrender/ 下载 Jsrender
添加对新依赖项的引用
在 Web 项目的 App_Start 目录下,使用 BundleConfig.cs 注册 bootstrap 文件
bundles.Add(new StyleBundle("~/Content/bootstrap/css"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap/js").Include("~/Scripts/bootstrap.js"));
bundles.Add(new ScriptBundle("~/bundles/custom").Include("~/Scripts/knockout-2.1.0.js", "~/Scripts/jsRender.js"));
bundles.Add(new ScriptBundle("~/bundles/demo").Include("~/Scripts/demo.js"));
在 _Layout.cshtml 中注册这些捆绑包
@Styles.Render("~/Content/themes/base/css",
"~/Content/css", "~/Content/bootstrap/css") @Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/custom")
….
@Scripts.Render("~/bundles/bootstrap/js")
JsRender
JsRender 是 jQuery 模板的新替代品。
Boris Moore 的更多示例:此处。
JSRender 的优势在于它比 jQuery 模板快得多,并提供了清晰的关注点分离。
在此示例中,我使用外部文件模板以实现更好的分离。JSRender 模板可以位于同一页面中,位于 <script id='myTemplate' type='text/x-jsrender'></script> 标签内。
在文件中使用模板的优势在于,模板可以更轻松地在不同页面上重复使用。
问题是 JSRender 如何找到要渲染的模板。
在我的示例中,我有一个 demo.js 文件,其中包含两个函数:.getPath 和 .renderTemplate: 它们会查找 Templates/HTML/ 文件夹。
getPath 函数使用命名约定来解析文件名,renderTemplate 函数加载文件 "_“ + name +”.tmpl.html”。
jQuery 的 .get() 函数将读取文件并将上下文加载到内存中,然后渲染模板并使用 Knockout.js 绑定数据。
Knockout.js 用于提供 MVVM 模式,触发绑定并刷新模板。
创建 JSRender 模板
首先,我将添加一个没有任何数据绑定的模板。
在 Web 项目中添加新文件夹 Templates/HTML
添加新的 HTML 文件
- _home.tmpl.html
- _head.tmpl.html
- _contacts.tmpl.html
删除新文件中的所有内容。
_header.tmpl.html 内容
<p>
To learn
more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">
Bla … bla… bla
</p>
_home.tmpl.html 内容
<h3>We suggest the following:</h3>
<ol class="round">
<li class="one">
<h5>Getting Started</h5>
Bla … bla… bla
</ol>
将 JSRender 模板绑定到视图
现在,我们将外部文件中的简单 jsrender 模板绑定到 Index.cshtml 视图中加载。
为了在 Index.cshtml 视图页面上显示模板,我们需要添加自定义脚本以与 knockout 库绑定。
我们将使用两个不同的 DIV 进行数据绑定:一个用于标题,一个用于正文。
Index.cshtml 应如下所示
@{
ViewBag.Title = "Home Page";
}
@section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>@ViewBag.Title.</h1>
<h2>@ViewBag.Message</h2>
</hgroup>
</div>
</section>
}
@Scripts.Render("~/bundles/demo")
<div data-bind="html: demo.head.headHtml" id="headHtml"></div>
<div data-bind="html: demo.body.bodyHtml"></div>
请注意本例中使用的命名空间 – demo。
创建自定义脚本
我将使用我们之前创建的自定义脚本文件来指定我们要加载的模板。这是一个通用函数,在异步读取模板文件完成后将使用异步进程渲染模板。
我们添加以下代码:
var demo = demo || {};
$(function() {
demo.utils = function () {
var getPath = function (name) {
return "../Templates/HTML/_" + name + ".tmpl.html";
};
var renderTemplate = function (item) {
var file = getPath(item.name);
$.when($.get(file))
.done(function (tmplData) {
$.templates({ tmpl: tmplData });
item.selector($.render.tmpl(item.data));
});
};
return {
getPath: getPath,
renderTemplate: renderTemplate
};
}();
});
我正在使用递归模式,其中函数会调用自身(注意函数末尾的 ())。
现在,为首页声明我们的 UI 视图模型,这可以放在单独的文件中,但为了简单起见,我将重用我们的 demo.js 文件。
现在我们可以将我们的模型添加到 demo.js 文件中。
$(function() {
demo.head = function() {
var headHtml = ko.observable(),
loadTemplate = demo.utils.renderTemplate({
name: "head",
data: "",
selector: headHtml
});
return {
loadTemplate: loadTemplate,
headHtml: headHtml
};
}();
demo.body = function() {
var bodyHtml = ko.observable(),
loadTemplate = demo.utils.renderTemplate({
name: "home",
data: "",
selector: bodyHtml
});
return {
bodyHtml: bodyHtml,
loadTemplate: loadTemplate
};
}();
demo.contacts = function() {
var
contactHtml = ko.observable(),
loadContacts = function() {
$.ajax({
url: '/Home/LoadContacts',
type: "POST",
/*contentType: "application/json; charset=utf-8",*/
dataType: 'json',
success: function(d) {
demo.utils.renderTemplate({
path: "../",
name: 'contacts',
data: d,
selector: contactHtml
});
}
});
};
return {
contactHtml: contactHtml,
loadContacts: loadContacts
};
}();
ko.applyBindings(demo.head);
ko.applyBindings(demo.body);
demo.contacts.loadContacts(); // Get data before binding template
ko.applyBindings(demo.contacts);
});
此时,如果我们运行应用程序,应该看不到原始 MVC 主页与我们自定义的主页之间的任何区别。
现在,我们想添加一个 JSRender 视图,它将绑定真实数据,而这些数据将来自服务器端。我们将通过 AJAX 调用检索数据。
打开 Contacts.cshtml 并修改它。它应该如下所示
@{
ViewBag.Title = "Contacts";
}
<hgroup class="title">
<h1>@ViewBag.Title.</h1>
<h2>@ViewBag.Message</h2>
</hgroup>
@Scripts.Render("~/bundles/demo")
<div data-bind="html: demo.contacts.contactHtml" id="headHtml"></div>
为了从控制器加载数据,我们将添加一个新的 AJAX 调用。
打开 HomeController.cs 并添加以下代码
[HttpGet]
public JsonResult LoadContacts()
{
var contacts = new List<Contact>
{
new Contact {fn = "Ben", ln = "Doe", title = "Developer",
email = "myemail@code.com", phone = "888-555-6565"},
new Contact {fn = "John", ln = "Smith", title = "Boss",
email = "boss@code.com", phone = "888-555-7777"}
};
return Json(contacts);
}
您还需要创建一个简单的 Contact 类
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Title { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
在我们的 demo.js 文件中,我们需要修改模板绑定,并在收到 AJAX 调用数据后加载模板。
指向最新版源代码项目的链接:此处。