自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

僅用100行代碼實(shí)現(xiàn)的JavaScript MVC樣式框架

開(kāi)發(fā) 前端
使用過(guò) JavaScript框架(如 AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用戶界面,前端)中mvc的工作機(jī)理。這些框架實(shí)現(xiàn)了MVC,使得在一個(gè)單頁(yè)面中實(shí)現(xiàn)根據(jù)需要變化視圖時(shí)更加輕松,而模型-視圖-控制器(mvc)的核心概念就是:處理傳入請(qǐng)求的控制器、顯示信息的視圖、表示業(yè)務(wù)規(guī)則和數(shù)據(jù)訪問(wèn)的模型。

Download JavaScript-Mvc.zip - 4.6 KB

介紹

使用過(guò) JavaScript框架(如 AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用戶界面,前端)中mvc的工作機(jī)理。這些框架實(shí)現(xiàn)了MVC,使得在一個(gè)單頁(yè)面中實(shí)現(xiàn)根據(jù)需要變化視圖時(shí)更加輕松,而模型-視圖-控制器(mvc)的核心概念就是:處理傳入請(qǐng)求的控制器、顯示信息的視圖、表示業(yè)務(wù)規(guī)則和數(shù)據(jù)訪問(wèn)的模型。

因此,當(dāng)需要?jiǎng)?chuàng)建這樣一個(gè)需要在單個(gè)頁(yè)面中實(shí)現(xiàn)切換出不同內(nèi)容的應(yīng)用時(shí),我們通常選擇使用上述框架之一。但是,如果我們僅僅需要一個(gè)在一個(gè)url中實(shí)現(xiàn)視圖切換的框架,而不需要額外捆綁的功能的話,就不必使用象Angular和Ember等復(fù)雜的框架。本文就是嘗試使用簡(jiǎn)單、有效方法來(lái)解決同樣的問(wèn)題。

 

概念

應(yīng)用中的代碼利用urls中的“#”實(shí)現(xiàn)MVC模式的導(dǎo)航。應(yīng)用以一個(gè)缺省的url開(kāi)始,基于哈希值的代碼加載應(yīng)用視圖并且將對(duì)象-模型應(yīng)用于視圖模板。

url格式像下面這樣:

http://Domain Name/index.html#/Route Name

視圖內(nèi)容必須以{{Property-Name}}的方式綁定對(duì)象模型的值和屬性。代碼會(huì)查找這個(gè)專門的模板格式并且代替對(duì)象模型中的屬性值。

以ajax的方式異步加載的視圖會(huì)被放置于頁(yè)面的占位符中。視圖占位符可以是任何的元素(理想的情況是div),但是它必須有一個(gè)專門的屬性,代碼根據(jù)這個(gè)專門的屬性來(lái)定位它,這樣同樣有助于代碼的實(shí)現(xiàn)。當(dāng)url改變時(shí),會(huì)重復(fù)這個(gè)場(chǎng)景,另外一個(gè)視圖被加載。聽(tīng)起來(lái)很簡(jiǎn)單吧!下面的流程圖解釋了在這個(gè)特定的實(shí)現(xiàn)中的消息跳轉(zhuǎn)。

寫代碼

我們以基本的模塊設(shè)計(jì)模式開(kāi)始,并且最終用門面設(shè)計(jì)模式的方式將我們的libs曝光于全局范圍內(nèi)。

 
  1. ; (function (w, d, undefined) { //rest of the code })(window, document); 

 

我們需要將視圖元素存儲(chǔ)到一個(gè)變量中,這樣就可以多次使用。

 
  1. var _viewElement = null//element that will be used to render the view 

 

我們需要一個(gè)缺省的路由來(lái)應(yīng)對(duì)url中沒(méi)有路由信息的情況,這樣就缺省的視圖就可以被加載而不是展示空白頁(yè)面。

 
  1. var _defaultRoute = null

 

現(xiàn)在我們來(lái)創(chuàng)建我們的主要MVC對(duì)象的構(gòu)造方法。我們會(huì)把路由信息存儲(chǔ)在“_routeMap”

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

 

是時(shí)候創(chuàng)建路由對(duì)象了,我們會(huì)將路由、模板、控制器的信息存儲(chǔ)在這個(gè)對(duì)象中。

 
  1. var routeObj = function (c, r, t) {  
  2.     this.controller = c;  
  3.     this.route = r;  
  4.     this.template = t;  

 

每一個(gè)url會(huì)有一個(gè)專門的路由對(duì)象routeObj.所有的這些對(duì)象都會(huì)被添加到_routeMap對(duì)象中,這樣我們后續(xù)就可以通過(guò)key-value的方式獲取它們。

為了添加路由信息到MVC libs中,我們需要曝光libs中的一個(gè)方法。所以讓我們創(chuàng)建一個(gè)方法,這個(gè)方法可以被各自的控制器用來(lái)添加新路由。

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

 

方法AddRoute接收3個(gè)參數(shù):控制器,路由和模板( contoller, route and template)。他們分別是:

controller:控制器的作用就是訪問(wèn)特定的路線。

route:路由的路線。這個(gè)就是url中#后面的部分。

template:這是外部的html文件,它作為這個(gè)路由的視圖被加載?,F(xiàn)在我們的libs需要一個(gè)切入點(diǎn)來(lái)解析url,并且為相關(guān)聯(lián)的html模板頁(yè)面提供服務(wù)。為了完成這個(gè),我們需要一個(gè)方法。

Initialize方法做如下的事情:

1)獲取視圖相關(guān)的元素的初始化。代碼需要一個(gè)具有view屬性的元素,這樣可以被用來(lái)在HTML頁(yè)面中查找:

2)設(shè)置缺省的路由

3)驗(yàn)證視圖元素是否合理

4)綁定窗口哈希變更事件,當(dāng)url不同哈希值發(fā)生變更時(shí)視圖可以被及時(shí)更新

5)***,啟動(dòng)mvc

 
  1. //Initialize the Mvc manager object to start functioning  
  2. jsMvc.prototype.Initialize = function () {  
  3.     var startMvcDelegate = startMvc.bind(this);  
  4.    
  5.     //get the html element that will be used to render the view    
  6.     _viewElement = d.querySelector('[view]');          
  7.     if (!_viewElement) return//do nothing if view element is not found      
  8.    
  9.     //Set the default route  
  10.     _defaultRoute = this._routeMap[Object.getOwnPropertyNames(this._routeMap)[0]];      
  11.    
  12.     //start the Mvc manager  
  13.     w.onhashchange = startMvcDelegate;  
  14.     startMvcDelegate();  

 

在上面的代碼中,我們從startMvc 方法中創(chuàng)建了一個(gè)代理方法startMvcDelegate 。當(dāng)哈希值變化時(shí),這個(gè)代理都會(huì)被調(diào)用。下面就是當(dāng)哈希值變化時(shí)我們做的操作的先后順序:

1)獲取哈希值

2)從哈希中獲取路由值

3)從路由map對(duì)象_routeMap中獲取路由對(duì)象routeObj 

4)如果url中沒(méi)有路由信息,需要獲取缺省的路由對(duì)象

5)***,調(diào)用跟這個(gè)路由有關(guān)的控制器并且為這個(gè)視圖元素的視圖提供服務(wù)

上面的所有步驟都被下面的startMvc方法所實(shí)現(xiàn)

 
  1. //function to start the mvc support  
  2. function startMvc() {  
  3.     var pageHash = w.location.hash.replace('#', ''),  
  4.         routeName = null,  
  5.         routeObj = null;                  
  6.            
  7.     routeName = pageHash.replace('/', ''); //get the name of the route from the hash          
  8.     routeObj = this._routeMap[routeName]; //get the route object      
  9.    
  10.     //Set to default route object if no route found  
  11.     if (!routeObj)  
  12.         routeObj = _defaultRoute;  
  13.        
  14.     loadTemplate(routeObj, _viewElement, pageHash); //fetch and set the view of the route  

 

下一步,我們需要使用XML HTTP請(qǐng)求異步加載合適的視圖。為此,我們會(huì)傳遞路由對(duì)象的值和視圖元素給方法loadTemplate。

 
  1. //Function to load external html data  
  2. function loadTemplate(routeObject, view) {  
  3.     var xmlhttp;  
  4.     if (window.XMLHttpRequest) {  
  5.         // code for IE7+, Firefox, Chrome, Opera, Safari  
  6.         xmlhttp = new XMLHttpRequest();  
  7.     }  
  8.     else {  
  9.         // code for IE6, IE5  
  10.         xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');  
  11.     }  
  12.     xmlhttp.onreadystatechange = function () {  
  13.         if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {  
  14.             loadView(routeObject, view, xmlhttp.responseText);  
  15.         }  
  16.     }  
  17.     xmlhttp.open('GET', routeObject.template, true);  
  18.     xmlhttp.send();  

 

當(dāng)前只剩加載視圖和將對(duì)象模型與視圖模板綁定了。我們會(huì)創(chuàng)建一個(gè)空的模型對(duì)象,然后傳遞與方法相關(guān)的模型來(lái)喚醒路由控制器。更新后的模型對(duì)象會(huì)與先前已經(jīng)加載的XHR調(diào)用中的HTML模板綁定。

loadView 方法被用于調(diào)用控制器方法,以及準(zhǔn)備模型對(duì)象。

replaceToken方法被用于與HTML模板一起綁定模型

  1. //Function to load the view with the template  
  2. function loadView(routeObject, viewElement, viewHtml) {  
  3.     var model = {};   
  4.    
  5.     //get the resultant model from the controller of the current route    
  6.     routeObject.controller(model);   
  7.    
  8.     //bind the model with the view      
  9.     viewHtml = replaceToken(viewHtml, model);   
  10.        
  11.     //load the view into the view element  
  12.     viewElement.innerHTML = viewHtml;   
  13. }  
  14.    
  15. function replaceToken(viewHtml, model) {  
  16.     var modelProps = Object.getOwnPropertyNames(model),  
  17.            
  18.     modelProps.forEach(function (element, index, array) {  
  19.         viewHtml = viewHtml.replace('{{' + element + '}}', model[element]);  
  20.     });  
  21.     return viewHtml;  

***,我們將插件曝光于js全局范圍外

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

 

現(xiàn)在,是時(shí)候在我們單頁(yè)應(yīng)用中使用這個(gè)MVC插件。在下一個(gè)代碼段中,下面這些會(huì)實(shí)現(xiàn):

1)在web頁(yè)面中引入這個(gè)代碼

2)用控制器添加路由信息和視圖模板信息

3)創(chuàng)建控制器功能

4)***,初始化lib。

除了上面我們需要的鏈接讓我們導(dǎo)航到不同的路徑外,一個(gè)容器元素的視圖屬性包含著視圖模板html。

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4.     <title>JavaScript Mvc</title> 
  5.     <script src="jsMvc.js"></script> 
  6.     <!--[if lt IE 9]> <script src="jsMvc-ie8.js"></script> <![endif]--> 
  7.        
  8.     <style type="text/css"> 
  9.         .NavLinkContainer {  
  10.             padding: 5px;  
  11.             background-color: lightyellow;  
  12.         }  
  13.    
  14.         .NavLink {  
  15.             background-color:black;  
  16.             color: white;  
  17.             font-weight:800;  
  18.             text-decoration:none;  
  19.             padding:5px;  
  20.             border-radius:4px;  
  21.         }  
  22.             .NavLink:hover {  
  23.                 background-color:gray;  
  24.             }  
  25.     </style> 
  26. </head> 
  27. <body> 
  28.     <h3>Navigation Links</h3> 
  29.     <div class="NavLinkContainer"> 
  30.         <a class="NavLink" href="index.html#/home">Home</a>   
  31.       
  32.         <a class="NavLink" href="index.html#/contact">Contact</a>   
  33.    
  34.         <a class="NavLink" href="index.html#/admin">Admin</a>   
  35.           
  36.     </div> 
  37.     <br /> 
  38.     <br /> 
  39.     <h3>View</h3> 
  40.     <div view></div> 
  41.     <script> 
  42.         jsMvc.AddRoute(HomeController, &apos;home&apos;, &apos;Views/home.html&apos;);  
  43.         jsMvc.AddRoute(ContactController, &apos;contact&apos;, &apos;Views/contact.html&apos;);  
  44.         jsMvc.AddRoute(AdminController, &apos;admin&apos;, &apos;Views/admin.html&apos;);  
  45.         jsMvc.Initialize();  
  46.    
  47.         function HomeController(model) {  
  48.             model.Message = &apos;Hello World&apos;;  
  49.         }  
  50.    
  51.         function ContactController(model) {  
  52.             model.FirstName = "John";  
  53.             model.LastName = "Doe";  
  54.             model.Phone = &apos;555-123456&apos;;  
  55.         }  
  56.    
  57.         function AdminController(model) {  
  58.             model.UserName = "John";  
  59.             model.Password = "MyPassword";  
  60.         }  
  61.     </script> 
  62. </body> 
  63. </html> 

上面的代碼有一段包含一個(gè)為IE的條件注釋。

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

如果IE的版本低于9,那么function.bind,Object.getOwnPropertyNames和Array.forEach屬性將不會(huì)被支持。因此我們要通過(guò)判斷瀏覽器是否低于IE9來(lái)反饋代碼是否支持。

其中的內(nèi)容有home.html, contact.html 和 admin.html 請(qǐng)看下面:

home.html:

  1. {{Message}} 

contact.html:

  1. {{FirstName}} {{LastName}}  
  2. <br /> 
  3. {{Phone}} 

admin.html:

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

完整的代碼可以從給定的下載鏈接中得到。

#p#

如何運(yùn)行代碼

運(yùn)行該代碼比較簡(jiǎn)單,需要在你喜歡的Web服務(wù)器上創(chuàng)建一個(gè)Web應(yīng)用,下面以IIS為例來(lái)說(shuō)明。

首先在默認(rèn)站點(diǎn)中新增一個(gè)Web應(yīng)用.

然后設(shè)置必填信息:別名,物理路徑,應(yīng)用池,用戶認(rèn)證信息,點(diǎn)擊OK。

***定位到Web應(yīng)用的內(nèi)容目錄,瀏覽你想打開(kāi)的HTML頁(yè)面即可。

跑在服務(wù)器里是必要的,因?yàn)榇a加載從存儲(chǔ)于外部文件中的視圖,瀏覽器不會(huì)允許我們的代碼在非宿主服務(wù)器環(huán)境下執(zhí)行。當(dāng)然如果你使用Visual Studio那么直接在目標(biāo)html文件上右鍵,選擇‘View In Browser’即可。

瀏覽器支持

大部分的現(xiàn)代瀏覽器都支持本代碼。針對(duì)IE8及以下的瀏覽器,有一份單獨(dú)的代碼來(lái)支持,但很不幸,這份代碼遠(yuǎn)多于100行。因此這代碼不是百分百跨瀏覽器兼容的,所以當(dāng)你決定在項(xiàng)目中使用時(shí)需要對(duì)代碼進(jìn)行微調(diào)。

興趣點(diǎn)

This example demonstrates這個(gè)示例向我們展示了對(duì)于非常明確地需求來(lái)說(shuō),真沒(méi)必要全部使用js庫(kù)和框架來(lái)實(shí)現(xiàn)。Web應(yīng)用是資源密集型的,***只使用必要的代碼而丟掉其他多余部分。

目前的代碼能做的就這些了。沒(méi)有諸如Web服務(wù)調(diào)用,動(dòng)態(tài)事件綁定功能的。很快我會(huì)提供支持更多特性的升級(jí)版本。

英文:JavaScript MVC Style Framework in Less Than 100 Lines of Code

 

 

 

責(zé)任編輯:林師授 來(lái)源: 開(kāi)源中國(guó)社區(qū)編譯
相關(guān)推薦

2021-03-08 15:04:48

編程Python代碼

2020-06-11 08:48:49

JavaScript開(kāi)發(fā)技術(shù)

2021-12-16 06:21:16

React組件前端

2009-07-01 14:23:46

JavaScript異

2023-11-27 07:10:06

日志中間件

2020-08-21 13:40:17

Python代碼人體膚色

2013-11-06 09:39:30

JavaScriptMVC框架

2022-05-11 09:02:27

Python數(shù)據(jù)庫(kù)Excel

2017-11-23 17:21:31

Yii框架IntelYii框架深度剖析

2012-02-09 16:09:17

JavaScript

2023-05-04 07:34:37

Rust代碼CPU

2017-04-05 11:10:23

Javascript代碼前端

2020-03-26 12:38:15

代碼節(jié)點(diǎn)數(shù)據(jù)

2015-05-05 11:12:50

JavaScriptMithril.js

2020-04-10 12:25:28

Python爬蟲代碼

2021-07-23 08:00:00

深度學(xué)習(xí)框架模型

2017-02-08 14:16:17

C代碼終端

2012-12-18 10:03:22

JavaScriptWebJS

2009-06-01 10:23:31

asp.net mvcasp.net mvc.net mvc框架

2022-07-07 09:19:24

JavaScript代碼樣式規(guī)則
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)