摘要:應(yīng)用以一個缺省的開始,基于哈希值的代碼加載應(yīng)用視圖并且將對象模型應(yīng)用于視圖模板。當哈希值變化時,這個代理都會被調(diào)用。英文原文譯文出處行代碼實現(xiàn)的樣式框架譯者妖怪姐無若船老大
Download JavaScript-Mvc.zip - 4.6 KB
JavaScript Mvc on Github
Live Demo
介紹使用過JavaScript框架(如AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用戶界面,前端)中mvc的工作機理。這些框架實現(xiàn)了MVC,使得在一個單頁面中實現(xiàn)根據(jù)需要變化視圖時更加輕松,而模型-視圖-控制器(mvc)的核心概念就是:處理傳入請求的控制器、顯示信息的視圖、表示業(yè)務(wù)規(guī)則和數(shù)據(jù)訪問的模型。
因此,當需要創(chuàng)建這樣一個需要在單個頁面中實現(xiàn)切換出不同內(nèi)容的應(yīng)用時,我們通常選擇使用上述框架之一。但是,如果我們僅僅需要一個在一個url中實現(xiàn)視圖切換的框架,而不需要額外捆綁的功能的話,就不必使用象Angular和Ember等復(fù)雜的框架。本文就是嘗試使用簡單、有效方法來解決同樣的問題。
概念應(yīng)用中的代碼利用urls中的“#”實現(xiàn)MVC模式的導(dǎo)航。應(yīng)用以一個缺省的url開始,基于哈希值的代碼加載應(yīng)用視圖并且將對象-模型應(yīng)用于視圖模板。
url格式像下面這樣:
http://**Domain Name**/index.html#/**Route Name**
視圖內(nèi)容必須以{{Property-Name}}的方式綁定對象模型的值和屬性。代碼會查找這個專門的模板格式并且代替對象模型中的屬性值。
以ajax的方式異步加載的視圖會被放置于頁面的占位符中。視圖占位符可以是任何的元素(理想的情況是div),但是它必須有一個專門的屬性,代碼根據(jù)這個專門的屬性來定位它,這樣同樣有助于代碼的實現(xiàn)。當url改變時,會重復(fù)這個場景,另外一個視圖被加載。聽起來很簡單吧!下面的流程圖解釋了在這個特定的實現(xiàn)中的消息跳轉(zhuǎn)。
寫代碼我們以基本的模塊設(shè)計模式開始,并且最終用門面設(shè)計模式的方式將我們的libs曝光于全局范圍內(nèi)。
; (function (w, d, undefined) { //rest of the code })(window, document);
我們需要將視圖元素存儲到一個變量中,這樣就可以多次使用。
var _viewElement = null; //element that will be used to render the view
我們需要一個缺省的路由來應(yīng)對url中沒有路由信息的情況,這樣就缺省的視圖就可以被加載而不是展示空白頁面。
var _defaultRoute = null;
現(xiàn)在我們來創(chuàng)建我們的主要MVC對象的構(gòu)造方法。我們會把路由信息存儲在“_routeMap”中
var jsMvc = function () { //mapping object for the routes this._routeMap = {}; }
是時候創(chuàng)建路由對象了,我們會將路由、模板、控制器的信息存儲在這個對象中。
var routeObj = function (c, r, t) { this.controller = c; this.route = r; this.template = t; }
每一個url會有一個專門的路由對象routeObj.所有的這些對象都會被添加到_routeMap對象中,這樣我們后續(xù)就可以通過key-value的方式獲取它們。
為了添加路由信息到MVC libs中,我們需要曝光libs中的一個方法。所以讓我們創(chuàng)建一個方法,這個方法可以被各自的控制器用來添加新路由。
jsMvc.prototype.AddRoute = function (controller, route, template) { this._routeMap[route] = new routeObj(controller, route, template); }
方法AddRoute接收3個參數(shù):控制器,路由和模板(contoller, route and template)。他們分別是:
controller:控制器的作用就是訪問特定的路線。
route:路由的路線。這個就是url中#后面的部分。
template:這是外部的html文件,它作為這個路由的視圖被加載。現(xiàn)在我們的libs需要一個切入點來解析url,并且為相關(guān)聯(lián)的html模板頁面提供服務(wù)。為了完成這個,我們需要一個方法。
Initialize方法做如下的事情:
獲取視圖相關(guān)的元素的初始化。代碼需要一個具有view屬性的元素,這樣可以被用來在HTML頁面中查找:
設(shè)置缺省的路由
驗證視圖元素是否合理
綁定窗口哈希變更事件,當url不同哈希值發(fā)生變更時視圖可以被及時更新
最后,啟動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方法中創(chuàng)建了一個代理方法startMvcDelegate。當哈希值變化時,這個代理都會被調(diào)用。下面就是當哈希值變化時我們做的操作的先后順序:
獲取哈希值
從哈希中獲取路由值
從路由map對象_routeMap中獲取路由對象routeObj
如果url中沒有路由信息,需要獲取缺省的路由對象
最后,調(diào)用跟這個路由有關(guān)的控制器并且為這個視圖元素的視圖提供服務(wù)
上面的所有步驟都被下面的startMvc方法所實現(xiàn)
//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(); }
當前只剩加載視圖和將對象模型與視圖模板綁定了。我們會創(chuàng)建一個空的模型對象,然后傳遞與方法相關(guān)的模型來喚醒路由控制器。更新后的模型對象會與先前已經(jīng)加載的XHR調(diào)用中的HTML模板綁定。
loadView方法被用于調(diào)用控制器方法,以及準備模型對象。
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();
現(xiàn)在,是時候在我們單頁應(yīng)用中使用這個MVC插件。在下一個代碼段中,下面這些會實現(xiàn):
在web頁面中引入這個代碼
用控制器添加路由信息和視圖模板信息
創(chuàng)建控制器功能
最后,初始化lib。
除了上面我們需要的鏈接讓我們導(dǎo)航到不同的路徑外,一個容器元素的視圖屬性包含著視圖模板html。
JavaScript Mvc Navigation Links
View
上面的代碼有一段包含一個為IE的條件注釋。
如果IE的版本低于9,那么function.bind,Object.getOwnPropertyNames和Array.forEach屬性將不會被支持。因此我們要通過判斷瀏覽器是否低于IE9來反饋代碼是否支持。
其中的內(nèi)容有home.html, contact.html 和 admin.html 請看下面:
home.html:
{{Message}}
contact.html:
{{FirstName}} {{LastName}}
{{Phone}}
admin.html:
完整的代碼可以從給定的下載鏈接中得到。
如何運行代碼運行該代碼比較簡單,需要在你喜歡的Web服務(wù)器上創(chuàng)建一個Web應(yīng)用,下面以IIS為例來說明。
首先在默認站點中新增一個Web應(yīng)用.
然后設(shè)置必填信息:別名,物理路徑,應(yīng)用池,用戶認證信息,點擊OK。
最后定位到Web應(yīng)用的內(nèi)容目錄,瀏覽你想打開的HTML頁面即可。
跑在服務(wù)器里是必要的,因為代碼加載從存儲于外部文件中的視圖,瀏覽器不會允許我們的代碼在非宿主服務(wù)器環(huán)境下執(zhí)行。當然如果你使用Visual Studio那么直接在目標html文件上右鍵,選擇‘View In Browser’即可。
瀏覽器支持大部分的現(xiàn)代瀏覽器都支持本代碼。針對IE8及以下的瀏覽器,有一份多帶帶的代碼來支持,但很不幸,這份代碼遠多于100行。因此這代碼不是百分百跨瀏覽器兼容的,所以當你決定在項目中使用時需要對代碼進行微調(diào)。
興趣點This example demonstrates這個示例向我們展示了對于非常明確地需求來說,真沒必要全部使用js庫和框架來實現(xiàn)。Web應(yīng)用是資源密集型的,最好只使用必要的代碼而丟掉其他多余部分。
目前的代碼能做的就這些了。沒有諸如Web服務(wù)調(diào)用,動態(tài)事件綁定功能的。很快我會提供支持更多特性的升級版本。
英文原文:Nitij - JavaScript MVC Style Framework in Less Than 100 Lines of Code
譯文出處:100 行代碼實現(xiàn)的 JavaScript MVC 樣式框架
譯者:妖怪姐, jingxing05, 無若, 船老大
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/85525.html
摘要:為了將對象和視圖綁定在一起,我們需要設(shè)置一個回調(diào)函數(shù),當對象的屬性發(fā)生改變時發(fā)送一個更新視圖的通知。下面是值發(fā)生變化的時候調(diào)用的回調(diào)函數(shù),當然現(xiàn)在我們可以使用更簡單的進行數(shù)據(jù)的監(jiān)聽,這在我們后面的將會講到。 MVC MVC是一種設(shè)計模式,它將應(yīng)用劃分為3個部分:數(shù)據(jù)(模型)、展示層(視圖)和用戶交互層。結(jié)合一下下圖,更能理解三者之間的關(guān)系。showImg(https://segment...
摘要:為了將對象和視圖綁定在一起,我們需要設(shè)置一個回調(diào)函數(shù),當對象的屬性發(fā)生改變時發(fā)送一個更新視圖的通知。下面是值發(fā)生變化的時候調(diào)用的回調(diào)函數(shù),當然現(xiàn)在我們可以使用更簡單的進行數(shù)據(jù)的監(jiān)聽,這在我們后面的將會講到。 MVC MVC是一種設(shè)計模式,它將應(yīng)用劃分為3個部分:數(shù)據(jù)(模型)、展示層(視圖)和用戶交互層。結(jié)合一下下圖,更能理解三者之間的關(guān)系。showImg(https://segment...
摘要:目前只有和有這個概率。是快速開發(fā)應(yīng)用程序的前端工具包。調(diào)試工具前端的調(diào)試工具很多,比如,核心的的。前端流程部署,和現(xiàn)在幾乎是前端最流行的自動化的項目構(gòu)建工具正則表達式瀏覽器插件開發(fā)瀏覽器原理溝通能力優(yōu)秀 下圖是前端工程師圖解:showImg(http://upload-images.jianshu.io/upload_images/1807893-de7c7404345922b6.jp...
閱讀 2788·2021-11-23 09:51
閱讀 1750·2021-11-22 13:54
閱讀 2911·2021-11-18 10:02
閱讀 1019·2021-08-16 10:57
閱讀 3661·2021-08-03 14:03
閱讀 1951·2019-08-30 15:54
閱讀 3607·2019-08-23 14:39
閱讀 706·2019-08-23 14:26