通过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,如需转载请自行联系原作者

相关文章
|
8月前
|
JSON 前端开发 JavaScript
Mvc视图的4种提交方式
本文介绍了jQuery中get/post与ajax提交方式,以及原生JS通过请求头和FormData对象发送数据的方法。涵盖参数配置、请求类型、回调处理等要点,适用于表单及数据提交场景。
247 1
|
9月前
|
安全 数据安全/隐私保护
Web渗透-逻辑漏洞
逻辑漏洞主要因程序逻辑不严谨或复杂导致处理错误,常见于越权访问、密码修改、支付等环节。漏洞统计显示,越权操作和逻辑漏洞占比最高,尤其账号安全风险突出,如任意重置密码、验证码暴力破解等。漏洞分类中,越权访问分为水平越权(同权限用户间数据访问)和垂直越权(跨权限数据访问)。
398 0
Web渗透-逻辑漏洞
|
XML 安全 前端开发
一行代码搞定禁用 web 开发者工具
在如今的互联网时代,网页源码的保护显得尤为重要,特别是前端代码,几乎就是明文展示,很容易造成源码泄露,黑客和恶意用户往往会利用浏览器的开发者工具来窃取网站的敏感信息。为了有效防止用户打开浏览器的 Web 开发者工具面板,今天推荐一个不错的 npm 库,可以帮助开发者更好地保护自己的网站源码,本文将介绍该库的功能和使用方法。 功能介绍 npm 库名称:disable-devtool,github 路径:/theajack/disable-devtool。从 f12 按钮,右键单击和浏览器菜单都可以禁用 Web 开发工具。 🚀 一行代码搞定禁用 web 开发者工具 该库有以下特性: • 支持可配
1481 22
|
计算机视觉 Python
Flask学习笔记(六):基于Flask的摄像头-web显示代码(可直接使用)
这篇文章是关于如何使用Flask框架结合OpenCV库,通过电脑摄像头实现视频流在网页上的实时显示,并提供了单摄像头和多摄像头的实现方法。
628 2
Flask学习笔记(六):基于Flask的摄像头-web显示代码(可直接使用)
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
408 3
|
存储 前端开发 测试技术
MVC、MVP、MVVM 模式
MVC、MVP 和 MVVM 是三种常见的软件架构模式,用于分离用户界面和业务逻辑。MVC(Model-View-Controller)通过模型、视图和控制器分离数据、界面和控制逻辑;MVP(Model-View-Presenter)将控制逻辑移到 Presenter 中,减少视图的负担;MVVM(Model-View-ViewModel)通过数据绑定机制进一步解耦视图和模型,提高代码的可维护性和测试性。
|
设计模式 开发框架 前端开发
MVC 模式在 C# 中的应用
MVC(Model-View-Controller)模式是广泛应用于Web应用程序开发的设计模式,将应用分为模型(存储数据及逻辑)、视图(展示数据给用户)和控制器(处理用户输入并控制模型与视图交互)三部分,有助于管理复杂应用并提高代码可读性和维护性。在C#中,ASP.NET MVC框架常用于构建基于MVC模式的Web应用,通过定义模型、控制器和视图,实现结构清晰且易维护的应用程序。
379 2
|
XML JSON 安全
Web安全-代码注入
Web安全-代码注入
175 6
|
安全 JavaScript 前端开发
Web安全-逻辑错误漏洞
Web安全-逻辑错误漏洞
294 1