通过MVC模式将Web视图和逻辑代码分离

简介:
MVC 模式 (Model-View-Controller) 常被用在 Web 程序中。如 Struts 框架就是一个基于 MVC 模式的 Web 框架。所谓 MVC 模式,就是将视图(也就是客户端代码,包括 html javascript 等)和模型(和数据库及业务逻辑相关的 Java 代码)分开。并通过控制器将两者联系起来。这样做的好处可以使客户端开发人员和服务端开发人员的工作尽量分开,以使他们之间的干扰降到最低。      虽然象 Struts 这样的框架可以很好地 Model View 分离。但是对于客户端的代码,仍然存在着一定的视图和逻辑混合的现象。如下面的代码所示:

<! 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 代码,美工一般是不参与实现的。这些代码一般也应属于业务逻辑代码的一部分,虽然它们都在客户端运行,但可能也会处理一定的业务逻辑,如验证数据的正确性。尤其在AJAX 应用中,在客户端还会通过http 协议从服务端获取数据。这样就和业务逻辑绑定得更紧了。因此,如果将用于描述界面的html 和用于处理业务逻辑的javascript (渲染界面的javascript 除外)混在一起,非常不利于团队中负责这两方面的人员进行协调。
     最好的可能就是将这些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 >

     虽然上面的代码从某种程度上达到了视图和逻辑分离的效果。但仍然有着一定的联系。我们可以看到,两个<input> 标签的onclick 事件不还是引用着fun1 fun2 函数吗!其实美工人员是不关心这两个函数到底是做什么的,甚至并不需要知道它们的存在。那么是否有更高的方法呢?答案当然是肯定的,就是通过动态的方式指定onclick 事件,而这一切美工人员是完全没有感觉的。
     我们在文章的开头提到了 MVC 模式。其实在客户端也存在着一个 MVC 体系结构。我们可以将视图 (V) 看成是描述界面的 html css javascript 代码,而模型( M )可以看成是处理业务逻辑的 javascript 代码,而控制器( C )就是将这两类代码连接起来的代码(一般也是 javascript 代码)。
     在本文中给出了一个小例子来演示一下如何通过动态的方法将V M 分离。这个例子是通过<div> 实现的10 个小方块,点击其中的某一个,会将相应的数字追加到下方的文本框架中,并且加入了一些用javascript 实现的效果,如以一定间隔随机更新方块和数字的颜色,直接在文本框中输入数字后,相应的文本框和数字的颜色也会随机发生变化。界面效果如图1 所示。



                                         图1
     下面先来实现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 代码外,没有任何和业务逻辑有关的javascript 代码。但使用<script> 引用了一个叫addevents.js 的文件。在这个文件中将为这个程序添加相应的逻辑代码,也就是说,这个文件相当于MVC 中的M C
     动作装载事件是通过 window onload 事件完成的,代码如下:

window.onload  =  onLoad;   //  为onload指定事件函数

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 函数是如何实现的,代码如下:

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 函数的基本实现原理是先将<div> 中的所有元素删除,再向其中加入10 <div> 标签。在addButton 函数中有几个关键的函数需要讲解一下。
getNumberKeysDiv 函数
     这个函数用于获得叫 numberKeys <div> 标签,实现代码如下:

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;                
            }
        }
    }
}

     这个函数并不是直接通过<div> id 找到这个<div> ,而是通过<div> class 属性,这样可能更灵活,因为如果通过id <div> ,就必须要求美工必须将这个<div> 命名为numberKeys ,而如果通过查找包含numberKeys class 属性的<div> 会对美工的限制更少。因为,只有这个<div> 才会使用css 中的numberKeys
getRandomColor 方法
这个方法获得了一个随机的演示,返回了字符串类型,格式 #FFFFFF 。实现代码如下:

function  getRandomArbitary(min, max)
{    
    
return  Math.round(Math.random()  *  (max  -  min)  +  min);
}
function  getRandomColor()
{
    
var  red  =  getRandomArbitary( 0 255 ).toString( 16 );    
    
var  green  =  getRandomArbitary( 0 255 ).toString( 16 );
    
var  blue  =  getRandomArbitary( 0 255 ).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 函数获得了三个十进制的随机数(0-255 ),并将其转换为16 进制,并返回最终结果。
buttonOnClick 函数
这个函数是<div> 标签的onclick 事件函数,实现代码如下:

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(); 
    
}

     这个函数实现很简单,它的功能是将相应<div> 标签中的数字追加到numbers 文本框中。只是考虑了firefox ie 的不同。在firefox 中,获得<div> 中的文本要使用textContext ,而在ie 中要使用innerText 。最后再将当前点击的<div> 和数字的颜色再次变换。
     到现在为止,还有两个事件函数代码没有给出,这两个事件函数是onKeyup stopAndStartTimer
    onKeyup 函数
     numbers 文本框输入一个字符后,发生这个事件,实现代码如下:

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

     这个函数的实现代码也很简单。只是根据用户在文本框中输入的数字来找到相应的<div> 标签,并再次随机变换<div> 背景和数字的颜色。
stopAndStartTimer 函数
这个函数是用来控制定时器的,如果启动定时器,浏览器会每隔3 秒重新使<div> 随机变化一次颜色。实现代码如下:

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 文件外,并未涉及任何和逻辑有关的代码。而设计界面的美工也并不知道开发人员会为<div> 及其他的按钮和文本框添加什么动作。而美工要做的是调整和界面有关的东西,如颜色,位置,分割等。只要使用<script> 引用了这个js 文件,就可以很容易加入相应的动作,而要将这些动作去掉,删除或注释掉这个<script> 标签即可。
     尤其要提一下<div> 标签,美工在设计界面时可以向这个<div> 标签添加任何子元素。而在加入addevents.js 后,程序会自动将由美工向<div> 标签中的加入的内容都删除,而加入由业务逻辑需要的元素。这样美工用来设计界面的元素就不会影响开发人员需要加入的和业务逻辑有关的元素了。
     根据上面的代码不难看出,numberKeys.html 属于视图层,所有的事件函数属性模型层,而其他的javascript 代码都属性控制器(Controller)






 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/215345,如需转载请自行联系原作者

相关文章
|
1月前
|
计算机视觉 Python
Flask学习笔记(六):基于Flask的摄像头-web显示代码(可直接使用)
这篇文章是关于如何使用Flask框架结合OpenCV库,通过电脑摄像头实现视频流在网页上的实时显示,并提供了单摄像头和多摄像头的实现方法。
85 2
Flask学习笔记(六):基于Flask的摄像头-web显示代码(可直接使用)
|
19天前
|
存储 前端开发 测试技术
MVC、MVP、MVVM 模式
MVC、MVP 和 MVVM 是三种常见的软件架构模式,用于分离用户界面和业务逻辑。MVC(Model-View-Controller)通过模型、视图和控制器分离数据、界面和控制逻辑;MVP(Model-View-Presenter)将控制逻辑移到 Presenter 中,减少视图的负担;MVVM(Model-View-ViewModel)通过数据绑定机制进一步解耦视图和模型,提高代码的可维护性和测试性。
|
2月前
|
设计模式 开发框架 前端开发
MVC 模式在 C# 中的应用
MVC(Model-View-Controller)模式是广泛应用于Web应用程序开发的设计模式,将应用分为模型(存储数据及逻辑)、视图(展示数据给用户)和控制器(处理用户输入并控制模型与视图交互)三部分,有助于管理复杂应用并提高代码可读性和维护性。在C#中,ASP.NET MVC框架常用于构建基于MVC模式的Web应用,通过定义模型、控制器和视图,实现结构清晰且易维护的应用程序。
49 2
|
1月前
|
前端开发 Java
【案例+源码】详解MVC框架模式及其应用
【案例+源码】详解MVC框架模式及其应用
49 0
|
2月前
|
XML JSON 安全
Web安全-代码注入
Web安全-代码注入
24 6
|
2月前
|
安全 JavaScript 前端开发
Web安全-逻辑错误漏洞
Web安全-逻辑错误漏洞
23 1
|
2月前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
63 7
|
2月前
|
前端开发 测试技术 开发者
MVC模式在现代Web开发中有哪些优势和局限性?
MVC模式在现代Web开发中有哪些优势和局限性?
|
2月前
|
数据处理 Python
Django视图:构建动态Web页面的核心技术
Django视图:构建动态Web页面的核心技术
|
2月前
|
设计模式 前端开发 PHP
PHP中实现简易的MVC模式
【8月更文挑战第31天】 本文将引导你了解如何在PHP中应用MVC(Model-View-Controller)架构模式,通过一个简单的例子展示其实现过程。我们将从基础的概念出发,逐步深入到代码实践,最终让你能够自己动手构建一个简易的MVC框架。文章不仅提供理论知识,还包含具体的代码示例,帮助你更好地理解并运用MVC模式。

热门文章

最新文章