MVC4, JSRender和Knockout的整合示例

在现代Web开发中,将表示层、数据和逻辑清晰分离是一种常见的做法。HTML5/CSS3和jQuery的出现,使得能够显著地将客户端实现的重心转移到客户端。新的库如JSRender和Knockout进一步将关注点分离到客户端代码中。

本文将展示如何实现MVC4、JSRender和Knockout之间的整合。代码主要设计用来展示客户端技术,以便将数据从视图中解耦。这里仅使用控制器来模拟从存储库中检索数据。

首先,需要准备解决方案:

  1. 创建一个新的MVC4应用程序。
  2. 使用NuGet添加以下包:jQuery、Knockout、Autofac、Tweeter bootstrap。
  3. 从https://github.com/BorisMoore/jsrender/下载Jsrender。
  4. 添加新依赖项的引用。

在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中注册这些bundle: @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是jQuery模板的替代品。它比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模式并触发绑定和刷新模板。首先,将添加一个没有任何数据绑定的模板。

在web项目中添加新文件夹Templates/HTML,并添加新的html文件:_home.tmpl.html、_head.tmpl.html、_contacts.tmpl.html、_header.tmpl.html。

_header.tmpl.html的内容如下: <p> 要学习更多关于ASP.NET MVC,请访问 <a href="http://asp.net/mvc" title="ASP.NET MVC网站"> Bla … bla… </a> </p>

_home.tmpl.html的内容如下: <h3> 建议以下内容: </h3> <ol class="round"> <li class="one"> <h5> 入门 </h5> Bla … bla… </ol>

现在将绑定简单的jsrender模板从外部文件加载到Index.cshtml视图中。为了在Index.cshtml视图页面上显示模板,需要添加自定义脚本以与knockout库绑定。

将使用两个不同的DIV进行数据绑定:一个用于头部,一个用于主体: @{ ViewBag.Title = "首页"; } <section class="featured"> <div class="content-wrapper"> <hgroup class="title"> <h1> @ViewBag.Title. </h1> <h2> @ViewBag.Message </h2> </hgroup> </div> </section>

请注意在这种情况下使用名称空间——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", 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(); });

此时,如果运行应用程序,应该看不到原始MVC首页和自定义的首页之间的区别。现在想要添加JSRender视图,它将绑定真实数据,这些数据将来自服务器端。将通过AJAX调用检索数据。

打开Contacts.cshtml并进行修改。它应该看起来像这样: @{ ViewBag.Title = "联系人"; } <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; } }

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485