本文給大家分享的是一則翻譯過來的,由國外友人寫的如何簡單有效的實現javascript MVC樣式框架,算是一個MVC的入門教程,希望大家能夠喜歡。
介紹
使用過JavaScript框架(如AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用戶界面,前端)中mvc的工作機理。這些框架實現了MVC,使得在一個單頁面中實現根據需要變化視圖時更加輕松,而模型-視圖-控制器(mvc)的核心概念就是:處理傳入請求的控制器、顯示信息的視圖、表示業務規則和數據訪問的模型。
因此,當需要創建這樣一個需要在單個頁面中實現切換出不同內容的應用時,我們通常選擇使用上述框架之一。但是,如果我們僅僅需要一個在一個url中實現視圖切換的框架,而不需要額外捆綁的功能的話,就不必使用象Angular和Ember等復雜的框架。本文就是嘗試使用簡單、有效方法來解決同樣的問題。
概念
應用中的代碼利用urls中的“#”實現MVC模式的導航。應用以一個缺省的url開始,基於哈希值的代碼加載應用視圖並且將對象-模型應用於視圖模板。
url格式像下面這樣:
http://Domain Name/index.html#/Route Name
視圖內容必須以{{Property-Name}}的方式綁定對象模型的值和屬性。代碼會查找這個專門的模板格式並且代替對象模型中的屬性值。
以ajax的方式異步加載的視圖會被放置於頁面的占位符中。視圖占位符可以是任何的元素(理想的情況是div),但是它必須有一個專門的屬性,代碼根據這個專門的屬性來定位它,這樣同樣有助於代碼的實現。當url改變時,會重復這個場景,另外一個視圖被加載。聽起來很簡單吧!下面的流程圖解釋了在這個特定的實現中的消息跳轉。
寫代碼
我們以基本的模塊設計模式開始,並且最終用門面設計模式的方式將我們的libs曝光於全局范圍內。
;(function(w,d,undefined){//restofthecode})(window,document);
我們需要將視圖元素存儲到一個變量中,這樣就可以多次使用。
var_viewElement=null;//elementthatwillbeusedtorendertheview
我們需要一個缺省的路由來應對url中沒有路由信息的情況,這樣就缺省的視圖就可以被加載而不是展示空白頁面。
var_defaultRoute=null;
現在我們來創建我們的主要MVC對象的構造方法。我們會把路由信息存儲在“_routeMap”中
? 1 2 3 4 var jsMvc = function () { //mapping object for the routes this._routeMap = {}; }是時候創建路由對象了,我們會將路由、模板、控制器的信息存儲在這個對象中。
? 1 2 3 4 5 var routeObj = function (c, r, t) { this.controller = c; this.route = r; this.template = t; }每一個url會有一個專門的路由對象routeObj.所有的這些對象都會被添加到_routeMap對象中,這樣我們後續就可以通過key-value的方式獲取它們。
為了添加路由信息到MVC libs中,我們需要曝光libs中的一個方法。所以讓我們創建一個方法,這個方法可以被各自的控制器用來添加新路由。
? 1 2 3 jsMvc.prototype.AddRoute = function (controller, route, template) { this._routeMap[route] = new routeObj(controller, route, template); }方法AddRoute接收3個參數:控制器,路由和模板(contoller, route and template)。他們分別是:
controller:控制器的作用就是訪問特定的路線。
route:路由的路線。這個就是url中#後面的部分。
template:這是外部的html文件,它作為這個路由的視圖被加載。現在我們的libs需要一個切入點來解析url,並且為相關聯的html模板頁面提供服務。為了完成這個,我們需要一個方法。
Initialize方法做如下的事情:
1)獲取視圖相關的元素的初始化。代碼需要一個具有view屬性的元素,這樣可以被用來在HTML頁面中查找:
2)設置缺省的路由
3)驗證視圖元素是否合理
4)綁定窗口哈希變更事件,當url不同哈希值發生變更時視圖可以被及時更新
5)最後,啟動mvc
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //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)從路由map對象_routeMap中獲取路由對象routeObj
4)如果url中沒有路由信息,需要獲取缺省的路由對象
5)最後,調用跟這個路由有關的控制器並且為這個視圖元素的視圖提供服務
上面的所有步驟都被下面的startMvc方法所實現
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //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。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //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.