<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數(shù)據(jù)加載中……

    通過MVC模式將Web視圖和邏輯代碼分離

    本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

        MVC模式(Model-View-Controller)常被用在Web程序中。如Struts框架就是一個基于MVC模式的Web框架。所謂MVC模式,就是將視圖(也就是客戶端代碼,包括htmljavascript等)和模型(和數(shù)據(jù)庫及業(yè)務邏輯相關的Java代碼)分開。并通過控制器將兩者聯(lián)系起來。這樣做的好處可以使客戶端開發(fā)人員和服務端開發(fā)人員的工作盡量分開,以使他們之間的干擾降到最低。

        雖然象Struts這樣的框架可以很好地ModelView分離。但是對于客戶端的代碼,仍然存在著一定的視圖和邏輯混合的現(xiàn)象。如下面的代碼所示:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
        
    <head>
            
    <title></title>
            
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            
    <script type="text/javascript" >
            
    function fun1(obj) {  }
            
    function fun2() { }
            
    </script>        
        
    </head>
        
    <body>
            
    <input type="button" value="按鈕1 " onclick="fun1(this)"/>
            
    <input type="button" value="按鈕2 " onclick="fun2()"/>
             
        
    </body> 
    </html>

        從上面的代碼可以看出,html代碼和javascript代碼都混在了同一個html文件中。在一般情況下,客戶端的界面是由美工設計的,而對于javascript代碼,美工一般是不參與實現(xiàn)的。這些代碼一般也應屬于業(yè)務邏輯代碼的一部分,雖然它們都在客戶端運行,但可能也會處理一定的業(yè)務邏輯,如驗證數(shù)據(jù)的正確性。尤其在AJAX應用中,在客戶端還會通過http協(xié)議從服務端獲取數(shù)據(jù)。這樣就和業(yè)務邏輯綁定得更緊了。因此,如果將用于描述界面的html和用于處理業(yè)務邏輯的javascript(渲染界面的javascript除外)混在一起,非常不利于團隊中負責這兩方面的人員進行協(xié)調(diào)。

        最好的可能就是將這些javascript代碼從html代碼中分離。也許有很多人馬上就會想到,將這些javascript放到.js文件中,然后使用<script>標簽引用一下就ok了。代碼如下:

    fun.js文件

    function fun1(obj) { ... }

    function fun2() {... }


    index.html文件

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
        
    <head>
            
    <title></title>
            
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="fun.js">
    </script>
        
    </head>
        
    <body>
            
    <input type="button" value="按鈕1 " onclick="fun1(this)"/>
            
    <input type="button" value="按鈕2 " onclick="fun2()"/>
             
        
    </body> 
    </html>

        雖然上面的代碼從某種程度上達到了視圖和邏輯分離的效果。但仍然有著一定的聯(lián)系。我們可以看到,兩個<input>標簽的onclick事件不還是引用著fun1fun2函數(shù)嗎!其實美工人員是不關心這兩個函數(shù)到底是做什么的,甚至并不需要知道它們的存在。那么是否有更高的方法呢?答案當然是肯定的,就是通過動態(tài)的方式指定onclick事件,而這一切美工人員是完全沒有感覺的。

        我們在文章的開頭提到了MVC模式。其實在客戶端也存在著一個MVC體系結(jié)構(gòu)。我們可以將視圖(V)看成是描述界面的htmlcssjavascript代碼,而模型(M)可以看成是處理業(yè)務邏輯的javascript代碼,而控制器(C)就是將這兩類代碼連接起來的代碼(一般也是javascript代碼)。

        在本文中給出了一個小例子來演示一下如何通過動態(tài)的方法將VM分離。這個例子是通過<div>實現(xiàn)的10個小方塊,點擊其中的某一個,會將相應的數(shù)字追加到下方的文本框架中,并且加入了一些用javascript實現(xiàn)的效果,如以一定間隔隨機更新方塊和數(shù)字的顏色,直接在文本框中輸入數(shù)字后,相應的文本框和數(shù)字的顏色也會隨機發(fā)生變化。界面效果如圖1所示。



                                             圖1

        下面先來實現(xiàn)View。先看看如下的代碼:

     numberKeys.html

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
      
    <html>
          
    <head>
              
    <title></title>
              
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
              
    <link  rel="stylesheet"  type="text/css" href="my.css"/>
              
    <script type="text/javascript" src="addevents.js">
              
    </script>

          
    </head>
          
    <body>
              
    <input id ="changeColor" type="button" value="開始變換顏色" />
              
    <br/><br/>

              
    <div id ="nubmerKeys" class="numberKeys"  >    

              
    </div> 
              
    <br/><br/>
              
    <br/><br/>
              
    <input id="numbers" type="text" size="80"/>

          
    </body> 
      
    </html>    

        從上面的代碼可以看出,除了一些html代碼外,沒有任何和業(yè)務邏輯有關的javascript代碼。但使用<script>引用了一個叫addevents.js的文件。在這個文件中將為這個程序添加相應的邏輯代碼,也就是說,這個文件相當于MVC中的MC

        動作裝載事件是通過windowonload事件完成的,代碼如下:

    window.onload = onLoad;  // 為onload指定事件函數(shù)

    function onLoad()
    {
        
    var text = document.getElementById("numbers");
        
    if(text)
        {      
            text.onkeyup 
    = onKeyup;  // 為文本框指定onkeyup事件
        }
        
    var button = document.getElementById("changeColor");
        
    if(button)
        {
            button.onclick 
    = stopAndStartTimer;  // 為按鈕指定onclick事件
        }  
        addButton();  
    // 用于在<div>中加入10個<div>標簽作為小方塊,并指定onclick事件
    }

        下面先來看一下addButton函數(shù)是如何實現(xiàn)的,代碼如下:

    function addButton()
    {
        
    var div = getNumberKeysDiv();  // 獲得id為nubmerKeys的<div>標簽

        
    try
        {
            
    if(div)
            {
                
    // 刪除<div>中的所有子元素
                for(var i = div.childNodes.length - 1; i >= 0; i--)
                {
                    
    try
                    {   
                        div.removeChild(div.childNodes[i]);
                    }
                    
    catch(e)
                    {                    
                    }            
                } 
                
    // 為<div>標簽加10個子<div>標簽
                for(var i = 0; i < 10; i++
                {
                    
    var button = document.createElement("div"); 
                
                    button.className 
    = "button";        
                    button.style.left 
    = i * 61 + "px";
                    button.style.backgroundColor 
    = getRandomColor();
                    button.style.border
    ="solid 1px";
                    button.style.textAlign 
    = "center";
                    button.style.lineHeight 
    = "50px";      
                    button.style.color 
    = getRandomColor(); 
                            
                    button.onclick 
    = buttonOnClick;
                
                    div.appendChild(button);               
                    button.innerHTML  
    ="<b>" ++ "</b>";                
                }            
            }
        } 
        
    catch(e)
        { 
        }            
    }

        addButton函數(shù)的基本實現(xiàn)原理是先將<div>中的所有元素刪除,再向其中加入10<div>標簽。在addButton函數(shù)中有幾個關鍵的函數(shù)需要講解一下。

    getNumberKeysDiv函數(shù)

        這個函數(shù)用于獲得叫numberKeys<div>標簽,實現(xiàn)代碼如下:

    function getNumberKeysDiv()
    {
        
    var divs = document.getElementsByTagName("div");
        
        
    if(divs)
        {
            
    for(var i = 0; i < divs.length; i++)
            {
                
    var div = divs[i];
                
                
    if(div.className.toString().indexOf("numberKeys"0> -1)
                {  
                    
    return div;                
                }
            }
        }
    }

        這個函數(shù)并不是直接通過<div>id找到這個<div>,而是通過<div>class屬性,這樣可能更靈活,因為如果通過id<div>,就必須要求美工必須將這個<div>命名為numberKeys,而如果通過查找包含numberKeysclass屬性的<div>會對美工的限制更少。因為,只有這個<div>才會使用css中的numberKeys

    getRandomColor方法

    這個方法獲得了一個隨機的演示,返回了字符串類型,格式#FFFFFF。實現(xiàn)代碼如下:

    function getRandomArbitary(min, max)
    {    
        
    return Math.round(Math.random() * (max - min) + min);
    }
    function getRandomColor()
    {
        
    var red = getRandomArbitary(0255).toString(16);    
        
    var green = getRandomArbitary(0255).toString(16);
        
    var blue = getRandomArbitary(0255).toString(16);
        
    if(red.length == 1) red = "0" + red;
        
    if(green.length == 1) green = "0" + green;
        
    if(blue.length == 1) blue = "0" + blue;
        
        
    return "#" + red.toString(16+ green.toString(16+ blue.toString(16);
    }

        getRandomColor通過getRandomArbitary函數(shù)獲得了三個十進制的隨機數(shù)(0-255),并將其轉(zhuǎn)換為16進制,并返回最終結(jié)果。

    buttonOnClick函數(shù)

    這個函數(shù)是<div>標簽的onclick事件函數(shù),實現(xiàn)代碼如下:

    function buttonOnClick()
    {
        
    var text = document.getElementById("numbers");    
        
    if(typeof this.innerText == "#ff0000")
            text.value 
    = text.value + this.textContent;    
        
    else 
            text.value 
    = text.value + this.innerText;    
        
    this.style.backgroundColor = getRandomColor();              
        
    this.style.color =  getRandomColor(); 
        
    }

        這個函數(shù)實現(xiàn)很簡單,它的功能是將相應<div>標簽中的數(shù)字追加到numbers文本框中。只是考慮了firefoxie的不同。在firefox中,獲得<div>中的文本要使用textContext,而在ie中要使用innerText。最后再將當前點擊的<div>和數(shù)字的顏色再次變換。

        到現(xiàn)在為止,還有兩個事件函數(shù)代碼沒有給出,這兩個事件函數(shù)是onKeyupstopAndStartTimer

        onKeyup函數(shù)

        numbers文本框輸入一個字符后,發(fā)生這個事件,實現(xiàn)代碼如下:

    function onKeyup()
    {
        
    var value = this.value;
        
    if(value.length == 0return;
        
    var i = value.toString().substr(value.length - 11); 
        
    if(isNaN(i) == false)
        {    
            
    var div = getNumberKeysDiv();    
            
    if(div)
            {
                
    var button = div.childNodes[i];
                button.style.backgroundColor 
    = getRandomColor();              
                button.style.color 
    =  getRandomColor(); 
             
            }
        }
    }

        這個函數(shù)的實現(xiàn)代碼也很簡單。只是根據(jù)用戶在文本框中輸入的數(shù)字來找到相應的<div>標簽,并再次隨機變換<div>背景和數(shù)字的顏色。

    stopAndStartTimer函數(shù)

    這個函數(shù)是用來控制定時器的,如果啟動定時器,瀏覽器會每隔3秒重新使<div>隨機變化一次顏色。實現(xiàn)代碼如下:


    var time;

    function stopAndStartTimer()
    {
        
    if(this.value.toString().indexOf("停止",0> -1)
        {
            
    this.value = "開始變換顏色";
            clearInterval(time);            
        }
        
    else
        {
            
    this.value = "停止變換顏色";
            time 
    = setInterval(onLoad, 3000);
        }
    }

        從上面給出的代碼可以看出,在View層,除了<script>引用了一個javascript文件外,并未涉及任何和邏輯有關的代碼。而設計界面的美工也并不知道開發(fā)人員會為<div>及其他的按鈕和文本框添加什么動作。而美工要做的是調(diào)整和界面有關的東西,如顏色,位置,分割等。只要使用<script>引用了這個js文件,就可以很容易加入相應的動作,而要將這些動作去掉,刪除或注釋掉這個<script>標簽即可。

        尤其要提一下<div>標簽,美工在設計界面時可以向這個<div>標簽添加任何子元素。而在加入addevents.js后,程序會自動將由美工向<div>標簽中的加入的內(nèi)容都刪除,而加入由業(yè)務邏輯需要的元素。這樣美工用來設計界面的元素就不會影響開發(fā)人員需要加入的和業(yè)務邏輯有關的元素了。

        根據(jù)上面的代碼不難看出,numberKeys.html屬于視圖層,所有的事件函數(shù)屬性模型層,而其他的javascript代碼都屬性控制器(Controller)






    Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2008-05-19 16:11 銀河使者 閱讀(4163) 評論(10)  編輯  收藏 所屬分類: ajaxjavascriptweb 原創(chuàng)

    評論

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    很好.....謝謝
    2008-05-19 16:50 | 風月無情

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    ......................................
    2008-05-19 17:58 | sktt

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    ...............................
    2008-05-19 17:58 | sktt

    # re: 通過MVC模式將Web視圖和邏輯代碼分離[未登錄]  回復  更多評論   

    的確很清楚,但是在實際的開發(fā)過程中,頁面更復雜,完全剝離的代碼量會比較大,開發(fā)速度也會受到影響。
    樓主已經(jīng)在項目中這么用啦?
    2008-05-20 01:17 | A

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    同意樓上的說法,在實際項目中,能夠真正做到MVC就很不容易了,至于view端,往往是美工出PSD, 工程人員實現(xiàn),此時刻意的去將js抽離反而會影響效率。不要說struts幫我們實現(xiàn)了MVC分離,他的tag設計完全毀了MVC。
    2008-05-20 08:40 | HiMagic!

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    首先說明一下,本文只是談一種思想,并不是說在項目中一定要采用,或是在項目中的所有模塊都采用這種方法,就象ajax的項目中,有很多方法實現(xiàn),如可采用以數(shù)據(jù)為中心的方法,或是xml+XSLT,或是其他方式。但是我們完全有理由采用自定義的方法,或只采用最原始的方法。或是它們的組合。

    至于mvc模式的采用,或采用到什么程度,要看具體的需求,但有一點。采用任何一種技術(shù)或設計思想,一定要清楚地知道能為自己帶來什么好處(時間、效率或金錢上的收益)。且不可盲目跟風。除非是以學習為目的,否則最好不要采用這種并不明朗,或使用后果無法預料的技術(shù)。

    對于本文的方法,并不一定完全采用,也不必一定要采用。即使采用,也應盡量使用一些現(xiàn)成的framework、如json、jquery等。這樣會降低bug數(shù)。提高開發(fā)效率。但即使采用framework,知道如何手工實現(xiàn)也會對使用framework有很大的幫助。這也是本文的主要目的。

    2008-05-20 09:14 | 銀河使者

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    補充一句,采用任何技術(shù)不是目的,關鍵要看采用這種技術(shù)能給我們帶來什么。 正所謂“軟件創(chuàng)造客戶價值”。
    2008-05-20 09:17 | 銀河使者

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    又學到一招 謝謝樓主
    2008-05-21 18:55 | liangyi

    # re: 通過MVC模式將Web視圖和邏輯代碼分離[未登錄]  回復  更多評論   

    到現(xiàn)在還上火呢....沒達到理想效果
    2008-12-31 15:51 | wolf

    # re: 通過MVC模式將Web視圖和邏輯代碼分離  回復  更多評論   

    2009-06-06 23:35 | hello
    主站蜘蛛池模板: 亚洲视频在线免费观看| 亚在线观看免费视频入口| 亚洲成人黄色在线| 亚洲人成无码网站久久99热国产| 成年网站免费视频A在线双飞| 三上悠亚电影全集免费| 老外毛片免费视频播放| 亚洲第一综合天堂另类专| 亚洲国产精品美女| 亚洲邪恶天堂影院在线观看| 亚洲午夜福利AV一区二区无码| 免费看国产一级片| 午夜成年女人毛片免费观看| 18观看免费永久视频| 亚洲欧洲免费视频| 你懂的在线免费观看| sihu国产精品永久免费| 美女被爆羞羞网站在免费观看| 亚洲中文字幕乱码AV波多JI| 亚洲Av无码一区二区二三区| 亚洲日本在线观看| 亚洲av无码国产精品色午夜字幕 | 久久亚洲一区二区| 亚洲日本va中文字幕久久| 亚洲中文字幕无码爆乳av中文| 全部免费毛片在线| 免费人成在线观看网站视频| 日本a级片免费看| 国产免费私拍一区二区三区| 永久中文字幕免费视频网站| 日本高清免费不卡在线| 日韩一区二区在线免费观看 | 日韩欧美亚洲国产精品字幕久久久| 亚洲无吗在线视频| 亚洲精品色播一区二区 | 免费少妇a级毛片人成网| 亚洲精品成人片在线观看| 亚洲人成色77777在线观看大| 亚洲精品成人久久久| 亚洲午夜无码久久久久| 久久亚洲私人国产精品vA|