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

简介:
本文为原创,如需转载,请注明作者和出处,谢谢!

    MVC模式(Model-View-Controller)常被用在Web程序中。如Struts框架就是一个基于MVC模式的Web框架。所谓MVC模式,就是将视图(也就是客户端代码,包括htmljavascript等)和模型(和数据库及业务逻辑相关的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事件不还是引用着fun1fun2函数吗!其实美工人员是不关心这两个函数到底是做什么的,甚至并不需要知道它们的存在。那么是否有更高的方法呢?答案当然是肯定的,就是通过动态的方式指定onclick事件,而这一切美工人员是完全没有感觉的。

    我们在文章的开头提到了MVC模式。其实在客户端也存在着一个MVC体系结构。我们可以将视图(V)看成是描述界面的htmlcssjavascript代码,而模型(M)可以看成是处理业务逻辑的javascript代码,而控制器(C)就是将这两类代码连接起来的代码(一般也是javascript代码)。

    在本文中给出了一个小例子来演示一下如何通过动态的方法将VM分离。这个例子是通过<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中的MC

     动作装载事件是通过 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>" +i + "</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,而如果通过查找包含numberKeysclass属性的<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文本框中。只是考虑了firefoxie的不同。在firefox中,获得<div>中的文本要使用textContext,而在ie中要使用innerText。最后再将当前点击的<div>和数字的颜色再次变换。

    到现在为止,还有两个事件函数代码没有给出,这两个事件函数是onKeyupstopAndStartTimer

    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)

本文转自银河使者博客园博客,原文链接http://www.cnblogs.com/nokiaguy/archive/2008/05/18/1202196.html如需转载请自行联系原作者


银河使者

相关文章
|
4月前
|
设计模式 前端开发 数据库
深入理解MVC设计模式:构建高效Web应用程序的基石
【7月更文挑战第4天】在软件工程领域,设计模式是解决常见问题的一系列经过验证的方法。其中,Model-View-Controller(MVC)设计模式自诞生以来,便成为了构建用户界面,特别是Web应用程序的黄金标准。MVC通过将应用程序逻辑分离为三个核心组件,提高了代码的可维护性、可扩展性和重用性。本文将深入探讨MVC设计模式的原理,并通过一个简单的代码示例展示其应用。
165 0
|
2月前
|
安全 JavaScript 前端开发
Web安全-逻辑错误漏洞
Web安全-逻辑错误漏洞
24 1
|
2月前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
64 7
|
2月前
|
前端开发 测试技术 开发者
MVC模式在现代Web开发中有哪些优势和局限性?
MVC模式在现代Web开发中有哪些优势和局限性?
|
2月前
|
数据处理 Python
Django视图:构建动态Web页面的核心技术
Django视图:构建动态Web页面的核心技术
|
3月前
|
开发者 前端开发 Java
架构模式的诗与远方:如何在MVC的田野上,用Struts 2编织Web开发的新篇章
【8月更文挑战第31天】架构模式是软件开发的核心概念,MVC(Model-View-Controller)通过清晰的分层和职责分离,成为广泛采用的模式。随着业务需求的复杂化,Struts 2框架应运而生,继承MVC优点并引入更多功能。本文探讨从MVC到Struts 2的演进,强调架构模式的重要性。MVC将应用程序分为模型、视图和控制器三部分,提高模块化和可维护性。
48 0
|
3月前
|
Java 开发者 前端开发
Struts 2、Spring MVC、Play Framework 上演巅峰之战,Web 开发的未来何去何从?
【8月更文挑战第31天】在Web应用开发中,Struts 2框架因强大功能和灵活配置备受青睐,但开发者常遇配置错误、类型转换失败、标签属性设置不当及异常处理等问题。本文通过实例解析常见难题与解决方案,如配置文件中遗漏`result`元素致页面跳转失败、日期格式不匹配需自定义转换器、`&lt;s:checkbox&gt;`标签缺少`label`属性致显示不全及Action中未捕获异常影响用户体验等,助您有效应对挑战。
89 0
|
3月前
|
Java 前端开发 Apache
Apache Wicket与Spring MVC等Java Web框架大PK,究竟谁才是你的最佳拍档?点击揭秘!
【8月更文挑战第31天】在Java Web开发领域,众多框架各具特色。Apache Wicket以组件化开发和易用性脱颖而出,提高了代码的可维护性和可读性。相比之下,Spring MVC拥有强大的生态系统,但学习曲线较陡;JSF与Java EE紧密集成,但在性能和灵活性上略逊一筹;Struts2虽成熟,但在RESTful API支持上不足。选择框架时还需考虑社区支持和文档完善程度。希望本文能帮助开发者找到最适合自己的框架。
46 0
|
3月前
|
存储 前端开发 数据库
神秘编程世界惊现强大架构!Web2py 的 MVC 究竟隐藏着怎样的神奇魔力?带你探索实际应用之谜!
【8月更文挑战第31天】在现代 Web 开发中,MVC(Model-View-Controller)架构被广泛应用,将应用程序分为模型、视图和控制器三个部分,有助于提高代码的可维护性、可扩展性和可测试性。Web2py 是一个采用 MVC 架构的 Python Web 框架,其中模型处理数据和业务逻辑,视图负责呈现数据给用户,控制器则协调模型和视图之间的交互。
40 0
|
4月前
|
算法 计算机视觉 C++
web 丨 nft 元宇宙链游项目系统开发模式逻辑详细(成熟源码)
一、什么是元宇宙? 元宇宙指的是通过虚拟增强的物理现实,呈现收敛性和物理持久性特征的,基于未来互联网,具有链接感知和共享特征的 3D 虚拟空间。 大概可以从时空性、真实性、独立性、连接性四个方面交叉描述元宇宙:
下一篇
无影云桌面