HTML5离线 MVC: 第 1部分

分享于 

13分钟阅读

Web开发

  繁體 雙語

介绍

我的一位客户建立一个离线网络应用。 这个( 此刻)的目标是 iPad。 我已经不能透露这个特定项目的来源,我已经决定创建一系列 Highlight 特性,用于创建这样一个应用程序。 为此,我提出了一个简单的应用程序,你可以用来保存联系人的联系信息。

这里的目标是实际拥有离线视图。模型和 JavaScript。 为了以类似的方式处理它们 ASP.NET MVC处理它们。

我将在一系列文章中展示整个应用程序的不同部分。 我不确定什么顺序和多少篇文章会被 into。 但是,它们应该包括以下内容:

  • 创建一个 JavaScript MVC结构
  • 连接并与WebSql数据库进行交互
  • 通过ApplicationCache把整个东西 offline

前提条件

演示和文章依赖于较早的文章: Roll-your-own-A-JavaScript-routerJavaScript命名空间。 尽管最后一个对于这个代码的实际工作并不是真正重要的。 当你看到我的意思时,更多的是你知道

namespace("Demo.Controllers", function() {

但是我需要你知道的路由器代码。

接下来将使用 jQuery ( 当然),它将使用 mustache 模板引擎。 我已经用了很长时间了。 我不能试着用两种方法来拼接,但我觉得它不会解释这些东西。 我使用 mustache 作为 ASP.NET MVC使用 Razor。

将有两个命名空间: CoreDemo 内核将保存所有线索以创建MVC魔术。 演示将是实现。

在该文件夹中还可以找到 core.js。 这只是核心命名空间的开始,并保存一些 helper 函数。 其中最重要的是 Core.apply。 这个函数已经在我的工具箱中有一段时间了,它被证明是非常有用的。 我从Ext库中偷了这个,它做的是将一个对象复制到另一个。

控制器和视图

在这个artice中,我将带你浏览创建控制器和视图代码。 我不介意复杂的代码,但是将使多个视图工作的控制器应该是简单的。 在 ASP.NET MVC中的控制器看起来很简单。 所有的复杂性都被隐藏了:它们从哪个控制器类中。 这是我们将要采取的完全相同的方法。

主控制器最终看起来像最终结果的结果

namespace("Demo.Controllers", function(Namespace) {
 var Home=function() {
 //The construtor Core.apply(this, Core.Controller.prototype);
 return Core.Controller.apply(this, arguments);
 };
 Home.prototype.index=function(action, id) {
 //home/index//starts home/index.htmlthis.viewBag.datetime=new Date();
 this.view(); 
 }
 Namespace["Home"]=Home;
})

你会看到与 ASP.NET MVC相似的。 我们的mustache 模板将使用的viewBag。 而 this.view的声明将会告诉我们。 构造函数中的混乱我将进一步解释。

我们的视图模板可以如下所示

<h2>Home</h2><div>It's now {{datetime}}<div>

目录结构

为了获得视图,目录具有强制结构。 至少对于视图应该是什么位置。

  • 资产( 包含核心代码和 CSS 等等 )
  • 控制器
    • contacts.js
    • home.js
  • 视图
    • 联系人
      • contact.html
      • index.html
    • 主页
      • index.html
  • index.html

因此,路由"#home/索引"将使用"控制器/家庭。js"来获取视图" views/home/index.html"。

Core.Controller 类

在我们主控制器的构造函数中,我们看到一些奇怪的语句。 首 Core.apply(this, Core.Controller.prototype);return Core.Controller.apply(this, arguments); 第一种是继承的替代。 而不是正常的方式 Home.prototype=new Core.Controller(); 这将Prototype复制到自己。

"为什么因为 Core.Controller的构造函数不返回自身。 但它会返回一个函数。 如果你还没有阅读路由器文章现在你应该。。 完成路由器处理函数,而不是类。 它根据所提供的路径启动一个函数。 我觉得应该保持这种状态。 如果我们提供实际对象实例,它就会知道如何启动正确的函数 inside 它们。 我不想去那里。 但我希望它能启动一个实例。 通过向你展示主控制器的路由方式在主 index.html 中的设置方式,让我来阐明一下。

$(document).ready(function() {
 router.registerRoute("home/:action:/:id:", new Demo.Controllers.Home("home", "wrapper")); 
});

router.registerRoute 以函数作为参数。 但是在这里它也创建了一个主控制器的实例。 秘密在 Core.Controller 类里。

namespace("Core", function() {
 Core.Controller=function() {
 //what's the head part of our route?//this will be"home" coming from our constructor arguments!this.viewBasePath=arguments[0];
 //did we get a container id or should we just use body//e.g. the div to render the view in//this will be"wrapper" coming from our constructor arguments!this.container=arguments[1]? "#"+arguments[1]: "body";
 //the future data to be passed into the templatethis.viewBag={};
 //the view templates, we will cash them here to prevent http requestthis.viewTemplates={};
 //reference to ourself for the return function!var _self=this;
 returnfunction() {
 //we'll get the first argument out of our router function! Not the constructor!var controllerFunction=arguments[0]? arguments[0] : "index";
 //So now we'll have the controller(_self.viewBasePath) and the function within that controller _self.viewSubPath=controllerFunction;
 //Do we actually have this functionif(typeof _self[controllerFunction] == "function") {
 _self[controllerFunction].apply(_self, arguments);
 }
 else {
 _self.unknownView();
 }
 }
 }
........

就像你所看到的,它实际上返回一个函数。 这就是路由器启动的功能。 它通过下面的语句通过主控制器传递:

return Core.Controller.apply(this, arguments);

将这里函数 inline 与类实例保持一致的技巧是由JavaScript的函数范围引起的。 因为我们之前缓存了 _self。 JavaScript将在函数范围内向上移动查找 _self。 它将在 Core.Controller的构造函数中结束。 因为 return Core.Controller.apply(this, arguments); 范围现在是我们的主控制器,它拥有 Core.Controller的整个 Prototype。

也许你愿意在这一点上。 我不会责备你的,https://www.codeproject.com/script/Forums/Images/smiley_smile.gif

让我们先来看看:路由器启动了 Demo.Controllers.Home 类的一个实例,而他需要一个函数。 Demo.Controllers.Home 实例将 Core.Controller的原型复制到本身,并返回对 Core.Controller 原型构造函数的调用。 Core.Controller 实例设置一些变量,存储对自身的引用并返回一个函数,如果它是自己的实例到路由器。

这是一个很好的技巧,允许你将某个事件的实例传递给一个只接受函数的。 路由器不应该承受所有这些。 他是一个 trick,他应该保持这种状态。 虽然我使用自己的路由器,所以可以改变它,但是如果我更愿意使用第三方路由器,比如 ,我仍然可以这样使用它。 使用函数作为构造函数的返回值也提供了创建具有 private 函数和变量的类的可能性。 但那是为了不同的文章。 但是有一个缺点。 你不能用经典的继承 Home.prototype=new Core.Controller();

为什么不把它变成单独的Pattern?

这里只有一个主路由,所以为什么不让主控制器成为一个单独的? 原因是家庭不会是唯一的路线,我想隐藏 Core.Controller 中的复杂性。 所以我需要他的多个实例。

深入返回/路由器功能

让我们看看 Core.Controller 返回的实际函数:

var controllerFunction=arguments[0]? arguments[0] : "index";

我们已经让路由器去找

"home/:action:/:id:"
所以行动可能是空的。 在这种情况下我们会让它成为"索引"。
_self.viewSubPath=controllerFunction;

存储以供以后参考。

//Do we actually have this functionif(typeof _self[controllerFunction] == "function") {
 _self[controllerFunction].apply(_self, arguments);
}else {
 _self.unknownView();
}

如果我们有一个与操作变量具有相同 NAME的函数。 启动它。这将导致:

Home.prototype.index=function(action, id) {
 //home/index//starts home/index.htmlthis.viewBag.datetime=new Date();
 this.view(); 
}

视图函数

现在那部分是关于。 我们希望得到 views/home/index.html 并将它的粘贴到页面中。 因此 Core.Controller 具有视图函数。 如果它还没有存储的话,它将通过AJAX获得模板。 然后启动 renderView 函数,mustache 将把viewBag粘贴到模板中。 当我们最初设置路径时,变量 this.container 被传递到构造函数中。 它是包装器,显然应该是主中的某个 div to将模板粘贴在。

Core.Controller.prototype.view=function() {
 if(this.viewTemplates.hasOwnProperty(subView)) {
 //if we've already stored the template use thatthis.renderView(subView); 
 }
 else {
 //we didn't have this template, so we'll have to get it with jQueryvar _self=this;
 $.ajax({
 url: "views/"+this.viewBasePath+"/"+subView+".html",
 success: function(data) {
 _self.viewTemplates[subView]=data;
 _self.renderView(subView); 
 }
 });
 } 
}//Render the templateCore.Controller.prototype.renderView=function(subView) {
 //The container is #wrapper, which came from the contructor function//you could check here if this was alreay an jQuery object or just an id, but jQuery does that for you and I'm lazy $(this.container).html(Mustache.render(this.viewTemplates[subView], this.viewBag));
}

下载软件包中的内容

至少一个控制器。 联系人控制器。该控制器具有多个视图。 同时处理数据( of )。 所以应该更清楚一些。 把所有的东西放在文章里就会很长。 下载 it。这是真正理解本文的唯一方法。 如果你读到了这么远。

结束语

我必须承认,如果这个解释已经够清楚了,我还是没有什么知道的。 但请下载代码并运行它,阅读它,改变它。 在接下来的几篇文章中,我们将对 Core.Controller 类的使用更加清楚。

下一个将是建立方程的模型部分。


PAR  Html5  离线  
相关文章