页面逻辑与页面表现的分离,让你的Ajax编程更加模块化
大家都知道,没有人喜欢步行,给你个轮子,你去一个目的地的速度会大大提升。编程也是一样,给你个可复用的类,比自己一遍又一遍写一拖代码要省事的多。我们在写Java代码的时候知道要分模块,当然写Javascript也一样,我们天天写Java代码都知道,当所有的代码都耦合在一起的时候,无论是开发还是维护都无比烦躁,特别是我们做的后台系统的维护工作,很多时候,对于新功能的引进最好是无侵入式的,对于原有代码(无BUG的那种)改动越小越好,就像盖楼一样,你接着别人盖好的继续往上盖可以,但是你要把别人的转头上打个洞,硬塞一些新的东西,这个楼房不倒才怪^_^。带着这样的疑问,我们开始第二章的讲解,表现层的分层技巧。 Ok,还是来看上面的例子, PHP100Test.htm <script type="text/javascript" src="test.js"></script> <input type=”text” id=”comId” value=”请输入公司ID” onblur=”isExistCurComID(this.value)”> 当我们需要对于页面上的某个控件增加某个事件监听的时候,我们一般采用的做法是在某个具体控件上写上“事件名”=“方法”,这样的字段。好,我们来假设一下,有一个旧的系统,页面上20个Input text控件,现在我们对于其中部分控件,增加ajax验证的功能模块,我需要怎么做?如果采用老方法的话,就是说我们要破坏原有的页面,我们需要在每个控件上增加onblur失去焦点事件(举例,不见得是onblur),当其他类似页面需要此功能时候,我们也需要在改一次,成本是每改一个页面,该页面有多少控件,我们就要改多少次,而且改动位置不确定,CVS同步后会发现千疮百孔,有没有更好的方法?我们可以将onblur抽象出来吗?在原有页面只维持一处引用,而将所有的该ajax模块功能的代码都剥离到一个独立模块中吗?答案是可以的。 php程序员站 Test.htm <script type="text/javascript" src="test.js"></script> <input type=”text” id=”comId” value=”请输入公司ID” onblur=”isExistCurComID(this.value)”> <script> document.getElementsByName('comId')[0].onblur = function() { isExistCurComID(this.value); } </script> Test.js保持不变 发现了把?原本在元素comId上的onblur事件定义被移到了元素下方的script区域中,原本元素和事件的紧耦合关系变得开始松散,相互间的依赖由原来的元素自身内部依赖转移到外部的元素的唯一标示符,打个比方就是一个会飞的猪,现在被拆解成为,猪+(猪)会飞,猪没有变,但是猪会飞由原来的内部定义,被单独拉出来放在了外面。聪明的你马上就会从中得到启示,对的,这样的好处很明显,当我们需要给一个旧有的页面添加新的功能模块时,我们不需要对于原有代码做任何改动,所有的新功能都可以统一在外层定义和执行,而与事件依附对象的联系由原本的元素本身变为通过元素的唯一标示符找到该元素,同时对于功能的拆解也变的方便,当不需要某个功能的时候,只需要把相应的功能代码块去掉,是不是颇有模块化开发的味道,呵呵^_^。
for (var el in document.getElementByName('name')) { if(el.hasAttribute('attribute')){ el.getAttribute('attribute')=='value' return el; } } 第二个问题,我们刚才看到的是对于一个原本没有绑定onblur事件的元素,那么当我们面对一个已经有onblur事件的元素,如<input type=”text” id=”comId” name=”comId” onblur=”function(){}”>这样的元素时候,如果我们再定义一次document.getElementById('comId').onblur=function(){}那么就会把原来的onblur事件给盖掉,当然这个是我们不希望看到的,我们希望的结果是给该元素添加另外一个出发事件,同时不影响当前的事件。解决方法是: if (navigator.userAgent.indexOf("MSIE") > 0) { document.getElementById('comId').attachEvent('onblur',function() { // IE下的事件代码 }); } else { document.getElementById('comId').addEventListener('onblur',function() { // FF下的事件代码 }) } 第三个问题是,我们刚才对于一个元素,是在它下面定义了一块script区,当页面有多个元素需要这样的功能模块时,我们怎么做到批量的添加Ajax事件呢,难道还是要在每一个元素后写一段script区域代码?答案是否定的。我们应该把类似的script代码统一集中在一个地方,这样维护起来也方便,所以修改如下: Test.js文件内容修改 (function PageInit() { if (navigator.userAgent.indexOf("MSIE") > 0) { document.attachEvent('onload',function() { PageRegistedEvent(); }) www~phperz~com } else { document.addEventListener('onload',function() { PageRegistedEvent(); }) } function PageRegistedEvent() { if (navigator.userAgent.indexOf("MSIE") > 0) { document.getElementById('comId').attachEvent('onblur', function() { // FF下的事件代码 }) } } })(); 代码中定义了一个全局静态类PageInit(),该方法会在head加载Test.js时被执行,该方法注册了一个onload事件,当页面加载完毕后,会执行一个PageRegistedEventFor对应浏览器版本的方法,该方法里面定义了页面中所有元素的注册监听事件。 好了,到目前位置,我们已经把原本位于test.html文件中的所有Js脚本都被移到了test.js,在test.html中只在head里保留了对于test.js的引用,他们之间的联系建立在test.html的dom每个元素的唯一标记。相对于原本紧耦合的代码来说,这样的代码分离后,我们可以把test.js当作test.html的功能模块,可拆卸的,可复用的(基于页面的唯一标示符一直的理想情况下),易于维护和代码重构的(所有的逻辑代码都统一放在了test.js里面),从实现角度来说,看起来有点类似.net的code behind,只是这次分离的是表现层,把表现层分离为标准页面层和页面逻辑层。当然,仅仅是这样还是不够的,下面我们会从Javascirpt代码的角度来谈谈,对于表现层的页面逻辑层如何抽象和封装。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |