60行のコードで単一ページのWebアプリケーションフレームワークを記述する

序文として





Webデザインの人々は最近、単一ページのWebアプリケーションを試しました。 これは多くの場合正当化されます。

しかし、AngularJS、Ember、およびその他のノックアウトのようなものがなければ、単一ページのWebアプリケーションを実行できないと考えるのは明らかに間違いです。

いずれにせよ、To-doリストのような単純なことをする必要がある場合、メガバイトのメガフレームワークをクライアントにドラッグする必要はまったくありません。 実際、キロバイトのトラフィックは問題の半分です。 AngularJSの主な価格は、他のユニバーサルデータバインディングメカニズムと同様に、実行時の負荷が大きくなることです。



この記事では、60行のコード+ jQuery / Zeptoでシンプルなアプリフレームワークを作成し、負荷に不要なエンティティを追加せずにニーズに合わせて拡張する方法について説明します。



問題の声明





私たちのフレームワークは...:



  1. ...ルーティングのサポート、つまり 宣言モデルで「このURLハッシュをこのビューに表示する必要があります」と言う機会があるはずです。
  2. さまざまなビューを動的にロードできるようにする必要があります。 アプリケーションの一部は、起動が困難な場合や、権限のないユーザーなどには不要な場合があります。
  3. スクリプトを動的にロードできるようにする必要があります。 パラグラフ2に記載されている理由により
  4. 私たちのアプリケーションは閲覧履歴をサポートします-ブラウザの戻るボタンは前のページなどを表示するはずです
  5. アプリケーションのロジックが必要とするため、これらはすべてコンパクトで拡張可能である必要があります。




取得したいものの例





Bootstrapアプリケーション( 連絡先リスト )にはリスト自体が含まれ、カードには連絡先の詳細と特定のコントロールパネル(ダッシュボード)が含まれます。 そのパネルに何が表示されるかは重要ではありません。何か問題がないことはわかっています。



ペルソナのデモ







行こう...





単一ページのWebアプリケーションは、通常は静的な1つのhtmlファイルで構成されます。 しかし、設計上、明示的なサブページまたはビューがあります。 これらのサブページはマークアップの<section>要素で表されることに同意します。



<body> ... <section id=dashboard class="container" src="pages/dashboard.htm"></section> <section id=about class="container" src="pages/about.htm"></section> <section id=contact class="container" src="pages/contact.htm"></section> <section id=contacts class="container" src="pages/contacts.htm"></section> ... </body>
      
      







ここでは、非標準のsrc属性(セクション要素)を除き、すべてが明確になっています。

src属性は、このビューを表すために必要なhtmlフラグメントを指すことに同意します。 そのようなフラグメントは、オンデマンドでロードされます。 ユーザーがこのビューを表示するように要求した場合のみ。



次に、アクティブなクラスがインストールされたセクション要素が最新であり、それに応じて表示されることをWebデザイナーに同意します。 これを行うには、CSSルールが1つだけ必要です。



 /* section visibility */ body > section:not(.active) { display:none; }
      
      







ルーティング




アプリケーション内のナビゲーションはフォームのハイパーリンクを介して行われることをチームに同意します



つまり このようなハイパーリンクをアクティブにすると、id = "section-name"のセクション要素が表示されます。

ハイパーリンクを使用してパーツを表示すると、閲覧履歴の「すぐに使える」サポートが提供されます(ボタンは「進む」と「戻る」)。



この実装では、既製のhashchange()jQueryプラグインを使用しますが、ターゲットブラウザーがjQuery2でサポートされているブラウザーのみである場合、対応するイベントの通常のイベントハンドラーで十分です。



ロードされた「ページ」フラグメントの構造




この場合のダウンロード可能なフラグメントは、マークアップ(HTML自体)とスクリプトセクション(ページのハンドラー)で構成されます。 ここに例があります

pages / contact.htm-1つの連絡先を表示/編集するためのカード。



  <form class="form-horizontal" role="form" name="contactDetails"> ... </form> <script> app.handler(function() { //| //| view initialization: //| var $page = $(this); var $firstName = $("[name=firstName]"); var $lastName = $("[name=lastName]"); ... //| //| view presentation: //| return function(param) { var contact = data.contacts[param]; $firstName.val(contact.firstName); $lastName.val(contact.lastName); ... }; }); </script>
      
      







上記のコードでapp.handler(function() {...})



を呼び出すと、ビューが初期化され、データローダー関数がビューに登録されます。



それだけです。 アプリフレームワークのコード-これをすべて結び付ける非常に60行のコードをもたらすことは残っています。



原則として、ここでは特別なコメントなしですべてが明確になっているはずです。 しかし、口whiを吹くなら、恥ずかしがらないでください。



 // Simple single page application framework // Author: andrew @ terrainformatica.com (function($,window){ var pageHandlers = {}; var currentPage; // show the "page" with optional parameter function show(pageName,param) { // invoke page handler var ph = pageHandlers[pageName]; if( ph ) { var $page = $("section#" + pageName); ph.call( $page.length ? $page[0] : null,param ); // call "page" handler } // activate the page $(".nav li.active").removeClass("active"); $(".nav li a[href=#"+pageName+"]").closest("li").addClass("active"); $(document.body).attr("page",pageName) .find("section").removeClass("active") .filter("section#" + pageName).addClass("active"); } // "page" loader function app(pageName,param) { var $page = $(document.body).find("section#" + pageName); var src = $page.attr("src"); if( src && $page.find(">:first-child").length == 0) { $.get(src, "html") // it has src and is empty - load it .done(function(html){ currentPage = pageName; $page.html(html); show(pageName,param); }) .fail(function(){ $page.html("failed to get:" + src); }); } else show(pageName,param); } // register page handler app.handler = function(handler) { var $page = $(document.body).find("section#" + currentPage); pageHandlers[currentPage] = handler.call($page[0]); } function onhashchange() { var hash = location.hash || "#dashboard"; var re = /#([-0-9A-Za-z]+)(\:(.+))?/; var match = re.exec(hash); hash = match[1]; var param = match[3]; app(hash,param); // navigate to the page } $(window).hashchange( onhashchange ); // attach hashchange handler window.app = app; // setup the app as global object $(function(){ $(window).hashchange() }); // initial state setup })(jQuery,this);
      
      







上記のすべては、いくつかのモバイルWebアプリケーションで使用される実際のフレームワークからの絞り込みです。

モバイルの場合、アプリはapp.getData()



メソッドとapp.getData()



メソッドによって拡張されます。これは、localStorageのキャッシングとビュー切り替えアニメーションをサポートする$.ajax()



ラッパーです。 この機能は読者の想像に任せます。



All Articles