ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript MVC スタイルの超簡単実装フレームワーク_javascript スキル

JavaScript MVC スタイルの超簡単実装フレームワーク_javascript スキル

WBOY
WBOYオリジナル
2016-05-16 16:07:541292ブラウズ

はじめに

JavaScript フレームワーク (AngularJS、Backbone、Ember など) を使用したことのある人は、UI (ユーザー インターフェイス、フロントエンド) での mvc の動作メカニズムに精通しています。これらのフレームワークは MVC を実装しており、単一ページ内で必要に応じてビューを簡単に変更できるようにします。Model-View-Controller (mvc) の中心的な概念は、受信リクエストを処理するコントローラー、情報を表示するビュー、およびプレゼンテーション モデルです。ビジネスルールとデータアクセス用。

したがって、単一ページ内のさまざまなコンテンツを切り替える必要があるアプリケーションを作成する必要がある場合、通常は上記のフレームワークのいずれかを使用することを選択します。ただし、追加のバンドル機能なしで URL 内でビューの切り替えを実装するフレームワークだけが必要な場合は、Angular や Ember などの複雑なフレームワークを使用する必要はありません。この記事は、同じ問題を解決するために、シンプルかつ効果的な方法を使用する試みです。

コンセプト

アプリケーションのコードは、URL に「#」を使用して MVC モードのナビゲーションを実装します。アプリケーションはデフォルトの URL で開始され、ハッシュベースのコードがアプリケーション ビューを読み込み、オブジェクト モデルをビュー テンプレートに適用します。

URL の形式は次のとおりです:

http://ドメイン名/index.html#/ルート名

ビューのコンテンツは、オブジェクト モデルの値とプロパティを {{Property-Name}} の形式でバインドする必要があります。コードは、この特殊なテンプレート形式を検索し、オブジェクト モデル内のプロパティ値を置き換えます。

ajax 経由で非同期的にロードされたビューは、ページのプレースホルダーに配置されます。ビュー プレースホルダーは任意の要素 (理想的には div) にすることができますが、特別な属性が必要です。コードはこの特別な属性に基づいてビュー プレースホルダーを配置します。これは、コードの実装にも役立ちます。 URL が変更されると、シナリオが繰り返され、別のビューがロードされます。簡単そうに思えますか?以下のフロー図は、この特定の実装におけるメッセージ ジャンプを説明しています。

コードを書く

基本的なモジュール設計パターンから始めて、最後にファサード設計パターンを使用してライブラリをグローバル スコープに公開しました。

;(function(w,d,undefined){//restofthecode})(window,document);

ビュー要素を複数回使用できるように変数に保存する必要があります。

var_viewElement=null;//elementthatwillbeusedtorendertheview

URL にルーティング情報がない状況に対処するには、空白のページを表示する代わりにデフォルト ビューをロードできるように、デフォルト ルートが必要です。

var_defaultRoute=null;

次に、メイン MVC オブジェクトのコンストラクターを作成しましょう。ルーティング情報を「_routeMap」に保存します

var jsMvc = function () {
  //mapping object for the routes
  this._routeMap = {};
}

ルーティング オブジェクトを作成します。このオブジェクトにルーティング、テンプレート、コントローラー情報を保存します。

var routeObj = function (c, r, t) {
  this.controller = c;
  this.route = r;
  this.template = t;
}

各 URL には専用のルーティング オブジェクト、routeObj があり、これらのオブジェクトはすべて _routeMap オブジェクトに追加されるため、後でキーと値を介して取得できます。

MVC ライブラリにルーティング情報を追加するには、ライブラリ内のメソッドを公開する必要があります。そこで、それぞれのコントローラーで新しいルートを追加するために使用できるメソッドを作成しましょう。

jsMvc.prototype.AddRoute = function (controller, route, template) {
  this._routeMap[route] = new routeObj(controller, route, template);
}

メソッド AddRoute は、コントローラー、ルート、テンプレートの 3 つのパラメーターを受け取ります。それらは次のとおりです:

コントローラー: コントローラーの機能は、特定のルートにアクセスすることです。

ルート: ルーティングのルート。 URLの#以降の部分です。

テンプレート: これは、このルートのビューとしてロードされる外部 HTML ファイルです。ここで、ライブラリには URL を解析し、関連する HTML テンプレート ページを提供するためのエントリ ポイントが必要です。これを達成するには、メソッドが必要です。

Initialize メソッドは次のことを行います:

1) ビュー関連要素の初期化を取得します。このコードには、HTML ページ内での検索に使用できる view 属性を持つ要素が必要です:

2) デフォルトルートを設定します

3) ビュー要素が妥当かどうかを検証します

4) ウィンドウのハッシュ変更イベントをバインドし、URL の異なるハッシュ値が変更されると、時間内にビューを更新できます

5) 最後に、mvc を開始します

//Initialize the Mvc manager object to start functioning
jsMvc.prototype.Initialize = function () {
  var startMvcDelegate = startMvc.bind(this);
 
  //get the html element that will be used to render the view 
  _viewElement = d.querySelector('[view]');    
  if (!_viewElement) return; //do nothing if view element is not found  
 
  //Set the default route
  _defaultRoute = this._routeMap[Object.getOwnPropertyNames(this._routeMap)[0]];  
 
  //start the Mvc manager
  w.onhashchange = startMvcDelegate;
  startMvcDelegate();
}

上記のコードでは、startMvc メソッドからプロキシ メソッド startMvcDelegate を作成しました。このエージェントは、ハッシュ値が変更されるたびに呼び出されます。以下は、ハッシュ値が変更されたときに実行する一連の操作です:

1)ハッシュ値を取得します

2) ハッシュからルーティング値を取得します

3) ルートマップオブジェクト_routeMap

からルートオブジェクトrouteObjを取得します。

4) URL にルーティング情報がない場合は、デフォルトのルーティング オブジェクトを取得する必要があります

5) 最後に、このルートに関連するコントローラーを呼び出し、このビュー要素のビューにサービスを提供します

上記のすべての手順は、以下の startMvc メソッドによって実装されます

//function to start the mvc support
function startMvc() {
  var pageHash = w.location.hash.replace('#', ''),
    routeName = null,
    routeObj = null;        
     
  routeName = pageHash.replace('/', ''); //get the name of the route from the hash    
  routeObj = this._routeMap[routeName]; //get the route object  
 
  //Set to default route object if no route found
  if (!routeObj)
    routeObj = _defaultRoute;
   
  loadTemplate(routeObj, _viewElement, pageHash); //fetch and set the view of the route
}

  下一步,我们需要使用XML HTTP请求异步加载合适的视图。为此,我们会传递路由对象的值和视图元素给方法loadTemplate。

//Function to load external html data
function loadTemplate(routeObject, view) {
  var xmlhttp;
  if (window.XMLHttpRequest) {
    // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp = new XMLHttpRequest();
  }
  else {
    // code for IE6, IE5
    xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
  }
  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      loadView(routeObject, view, xmlhttp.responseText);
    }
  }
  xmlhttp.open('GET', routeObject.template, true);
  xmlhttp.send();
}

  当前只剩加载视图和将对象模型与视图模板绑定了。我们会创建一个空的模型对象,然后传递与方法相关的模型来唤醒路由控制器。更新后的模型对象会与先前已经加载的XHR调用中的HTML模板绑定。

  loadView方法被用于调用控制器方法,以及准备模型对象。

  replaceToken方法被用于与HTML模板一起绑定模型

//Function to load the view with the template
function loadView(routeObject, viewElement, viewHtml) {
  var model = {}; 
 
  //get the resultant model from the controller of the current route 
  routeObject.controller(model); 
 
  //bind the model with the view  
  viewHtml = replaceToken(viewHtml, model); 
   
  //load the view into the view element
  viewElement.innerHTML = viewHtml; 
}
 
function replaceToken(viewHtml, model) {
  var modelProps = Object.getOwnPropertyNames(model),
     
  modelProps.forEach(function (element, index, array) {
    viewHtml = viewHtml.replace('{{' + element + '}}', model[element]);
  });
  return viewHtml;
}

  最后,我们将插件曝光于js全局范围外

//attach the mvc object to the window
w['jsMvc'] = new jsMvc();

  现在,是时候在我们单页应用中使用这个MVC插件。在下一个代码段中,下面这些会实现:

  1)在web页面中引入这个代码

  2)用控制器添加路由信息和视图模板信息

  3)创建控制器功能

  4)最后,初始化lib。

  除了上面我们需要的链接让我们导航到不同的路径外,一个容器元素的视图属性包含着视图模板html。

<!DOCTYPE html>
<html>
<head>
  <title>JavaScript Mvc</title>
  <script src="jsMvc.js"></script>
  <!--[if lt IE 9]> <script src="jsMvc-ie8.js"></script> <![endif]-->
   
  <style type="text/css">
    .NavLinkContainer {
      padding: 5px;
      background-color: lightyellow;
    }
 
    .NavLink {
      background-color:black;
      color: white;
      font-weight:800;
      text-decoration:none;
      padding:5px;
      border-radius:4px;
    }
      .NavLink:hover {
        background-color:gray;
      }
  </style>
</head>
<body>
  <h3>Navigation Links</h3>
  <div class="NavLinkContainer">
    <a class="NavLink" href="index.html#/home">Home</a> 
  
    <a class="NavLink" href="index.html#/contact">Contact</a> 
 
    <a class="NavLink" href="index.html#/admin">Admin</a> 
    
  </div>
  <br />
  <br />
  <h3>View</h3>
  <div view></div>
  <script>
    jsMvc.AddRoute(HomeController, &apos;home&apos;, &apos;Views/home.html&apos;);
    jsMvc.AddRoute(ContactController, &apos;contact&apos;, &apos;Views/contact.html&apos;);
    jsMvc.AddRoute(AdminController, &apos;admin&apos;, &apos;Views/admin.html&apos;);
    jsMvc.Initialize();
 
    function HomeController(model) {
      model.Message = &apos;Hello World&apos;;
    }
 
    function ContactController(model) {
      model.FirstName = "John";
      model.LastName = "Doe";
      model.Phone = &apos;555-123456&apos;;
    }
 
    function AdminController(model) {
      model.UserName = "John";
      model.Password = "MyPassword";
    }
  </script>
</body>
</html>

  上面的代码有一段包含一个为IE的条件注释。

<!--[if lt IE 9]> <script src="jsMvc-ie8.js"></script> <![endif]-->

  如果IE的版本低于9,那么function.bind,Object.getOwnPropertyNames和Array.forEach属性将不会被支持。因此我们要通过判断浏览器是否低于IE9来反馈代码是否支持。

  其中的内容有home.html, contact.html 和 admin.html 请看下面:

  home.html:

{{Message}}

  contact.html:

{{FirstName}} {{LastName}}
<br />
{{Phone}}

  admin.html:

<div style="padding:2px;margin:2px;text-align:left;">
  <label for="txtUserName">User Name</label>
  <input type="text" id="txtUserName" value="{{UserName}}" />
</div>
<div style="padding:2px;margin:2px;text-align:left;">
  <label for="txtPassword">Password</label>
  <input type="password" id="txtPassword" value="{{Password}}" />
</div>

  完整的代码可以从给定的下载链接中得到。

 如何运行代码

  运行该代码比较简单,需要在你喜欢的Web服务器上创建一个Web应用,下面以IIS为例来说明。

  首先在默认站点中新增一个Web应用.

  然后设置必填信息:别名,物理路径,应用池,用户认证信息,点击OK。

  最后定位到Web应用的内容目录,浏览你想打开的HTML页面即可。

  跑在服务器里是必要的,因为代码加载从存储于外部文件中的视图,浏览器不会允许我们的代码在非宿主服务器环境下执行。当然如果你使用Visual Studio那么直接在目标html文件上右键,选择‘View In Browser'即可。

 浏览器支持

  大部分的现代浏览器都支持本代码。针对IE8及以下的浏览器,有一份单独的代码来支持,但很不幸,这份代码远多于100行。因此这代码不是百分百跨浏览器兼容的,所以当你决定在项目中使用时需要对代码进行微调。

 兴趣点

  This example demonstrates这个示例向我们展示了对于非常明确地需求来说,真没必要全部使用js库和框架来实现。Web应用是资源密集型的,最好只使用必要的代码而丢掉其他多余部分。

  目前的代码能做的就这些了。没有诸如Web服务调用,动态事件绑定功能的。很快我会提供支持更多特性的升级版本。

以上所述就是本文的全部内容了,希望能对大家熟练掌握javascript有所帮助。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。