




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
AJAX表格分页模板:探讨基于Prototype框架的 javascript面向对象设计 2008-04-30 作者:笨笨狗 出处: 数据分页显示,是很普遍的需求,传统的实现大多是基于服务器端导航的,这种设计采用同步方式进行数据 传输,用户体验很差。下面是我在学习ajax的过程中,实现的一个解决方案,不知道设计得怎么样,所以想发出来给大家参考下,恳请给予建议和指导,狗狗感 激不尽!需求概述:需要将二维数据通过表格展现给客户端,用户可以事先选择每页显示的条目数,以及数据获取方式(静态获取、异步缓存,以及异步非缓存)。三种方式 简述如下1、静态获取方式:一次性获取全部数据,切换页面显示时,不再发起新的异步查询,适合少量数据的分页显示。2、异步缓存方式:分次异步获取页面内容,并缓存访问过的页面内容,下一次访问相同页面时,直接显示缓存内容,适合量较大且内容更新频率慢的数据显示。3、异步非缓存方式:与第二种方式类似,只是并不缓存页面内容,每次切换新页面都发起一次异步请求,适合更新频率快的数据显示。使用技术:客户端1、使用table定义二维数据结构,这是table最合理的使用方式;2、使用css控制页面展现;3、使用javascript发起异步查询,以及操作页面dom元素。为加快开发速度,采用成熟的Prototype框架简化复杂度。服务器端1、因为只是原型设计,决定采用Groovy脚本生成响应数据快速展示。只要遵循数据传输格式,能很快替换为别的实现。2、采用MySql做数据存储,模仿分页数据。实现过程:首先,设计静态效果页面,注意按照web标准采用合适的xhtml结构,并使用css控制其表现,页面代码如下,为简单起见,这里把css代码直接写到 head头中:xml 代码1. 2. 3. 4. 分页模板 5. 6. * 7. margin:0; 8. padding:0; 9. font:12px宋 体; 10. 11. body 12. text-align:center; 13. 14. #option 15. margin:20pxauto; 16. 17. #items 18. width:4em; 19. 20. #TMPwrap 21. text-align:center; 22. margin-top:10px; 23. 24. #pages 25. margin:10pxauto; 26. border-collapse:collapse; 27. border:1px#666solid; 28. 29. #pagescaption 30. width:100%; 31. 32. #pagesth 33. padding:0.5em; 34. border-right:1px#B9B4A1solid; 35. background:#ECE9D8url(images/theadbg.gif)repeat-xbottom; 36. text-align:center; 37. 38. #pagestd 39. border:1px#B9B4A1solid; 40. border-top:none; 41. padding:0.5em; 42. 43. #navigation 44. margin:10px; 45. text-align:center; 46. 47. #navigationa 48. margin-right:8px; 49. color:black; 50. 51. #navigationa.active 52. text-decoration:none; 53. color:red; 54. cursor:default; 55. 56. .hidden 57. display:none; 58. 59. 60. 61. 62. 63. 每页显示条 数: 64. 65. 获取方式: 66. 67. 静态 68. 异 步缓存 69. 异步非缓存 70. 71. 72. 73. 74. 75. 静态分页模板 76. 77. 78. 标 题一 79. 标 题二 80. 标 题三 81. 标 题四 82. 标 题五 83. 标 题六 84. 85. 86. 87. 88. 1 89. 1 90. 1 91. 1 92. 1 93. 1 94. 95. 96. 2 97. 2 98. 2 99. 2 100. 2 101. 2 102. 103. 104. 3 105. 3 106. 3 107. 3 108. 3 109. 3 110. 111. 112. 4 113. 4 114. 4 115. 4 116. 4 117. 4 118. 119. 120. 121. 122. 1 123. 2 124. 3 125. 126. 127. 128. 这样我们就制作了一个包含四行数据的表格。注意这里html标签的运用,使用thead、tbody将表格内容分成逻辑 块,在后面的设计中,我们会把每一页的内容生成一个tbody。为保证兼容性,对表格的修饰,比如边框、背景、底色这些,最好在单元格(td或者th)中 设定,以确保在不同的浏览器中具有相似的显示效果。以上内容中,我们用静态页面的方式,设计出了分页模板的表现形式,接下来让我们利用javascript这个强大的操盘手 来粘合其余的部分吧。第一步,我们需要设计一个抽象的基类,来实现代码复用(js的OO,不就是为了这个么,还有就是方便管理代码而已)。 首先,我们搞个命名空间来管理基类及其子类: js 代码1. varTbi=newObject();/全局命名空间 为啥叫“Tbi”?就不要问了,项目组的名称而已,呵呵:)接下来考虑我们的模板基类,他有什么特征 呢?1、需要持有一个到页面容器的引用,以便将自身加入页面流;2、需要保存用户设定的每页显示条目数;3、需要保存获取分页数据的服务器端地址(URL);这些成员可以通过构造器来初始化,除此之外,为了避免数据更新发生混乱(这个在异步非缓存的时候需要注意),还要有一个全局异步对象来获取数据,但不需要 通过参数提供。定义了成员变量,模板对象还需要有可操作的方法:1、构造函数:initialize,这个方法在构建Prototype风格构建类,实例化对象的时候会自动调用。另外有一些技巧下面会提到;2、在数据获取过程中,显示等待信息的方法:_showMessage,这里只是简单显示一句话,可以按需替换成显示图片等;3、显示模板初始页面的show方法(其中有两个故意设计的事件入口,供今后扩展使用):A、调用beforeShow,默认为空方法,什么也不做,可按需设定;B、调用_display方法,显示模板初始页面:a、调用2中的方法显示等待信息;b、调用_catchContent方法异步获取服务器数据。此方法可由所有模板共享,因此放到基类中达到代码重用。可以看到, 我们为了细粒度的控制Prototype的ajax封装,使用了transport属性。c、在成功返回服务器数据之后,addContent方法将把分页内容添加到容器中,分两步来做:(1) addPage方法作为回调函数添加模板主体抽象方法,由子类实现。(2) addNavigation方法根据实际情况生成并添加分页导航抽象方法,我将它在一个子类中实现然后演示混入(mixin),其实完全可以在基类中 提供达到同样的代码复用效果。js 代码1. /* 2. *模板基类 3. */ 4. Tbi.Template=Class.create(); 5. Tbi.Ttotype= 6. initialize:function() 7. this._init.apply(this,arguments); 8. , 9. 10. _init:function(wrap,items,catchUrl) 11. this.wrap=$(wrap); 12. this.items=items; 13. this.catchUrl=catchUrl; 14. this.ajax=null;/全局异步对象 15. , 16. 17. /显 示等待信息 18. _showMessage:function(text) 19. this.wrap.innerHTML=text; 20. , 21. 22. /显示模板 默认页面 23. show:function() 24. this.beforeShow();/显示前事件处理入口 25. this._display(); 26. this.afterShow();/显示后时间处理入口 27. , 28. 29. /显 示前事件处理入口 30. beforeShow:function(), 31. 32. _display:function() 33. this._showMessage(正在获取数据,请稍等); 34. this._catchContent(); 35. , 36. 37. /取得 默认页面内容,由两个模板公用 38. _catchContent:function() 39. if(this.ajax) 40. this.ajax.transport.abort(); 41. 42. this.ajax=newAjax.Request( 43. this.catchUrl, 44. 45. method:get, 46. parameters:mode:this.mode,items:this.items, 47. onComplete:this.addContent.bind(this) 48. 49. ); 50. , 51. 52. /添加页面 内容 53. addContent:function(xmlhttp) 54. this.addPage(xmlhttp);/抽象方法,添加页面内容 55. this.addNavigation();/抽象方法,添加分页导航 56. , 57. 58. /显示后事 件处理入口 59. afterShow:function() 60. 一些技巧:为了实现在子类中覆盖initialize构造函数,我们只需要将基类的成员初始化工作委托给_init方法即可,下面会看到他的作用。模仿事件处理机制,我们留下了两个事件入口beforeShow和afterShow,分别可以设置显示前事前和显示后事件。Prototype为Function对象扩展了一个bind方法和bindAsEventListener方法,可以很方便的将函数上下文(this) 切换为别的对象,这里,我们切换为模板对象。bind和bindAsEventListener的功用相似,但是有一点区别,用bind切换的方法,如果 有自动传入的参数,比如事件对象event,那么这个参数将被自动传入函数参数列表的最后,而后者则是自动传入函数参数列表的最前面,这个技巧很常用。比 如改写一下上面的代码,我给onComplete事件传入一个自定义参数tmyArg,使用两种不同的绑定 方法(xmlhttp是Prototype自动传入回调函数的参数):js 代码1. /用bind方 法 2. this.addContent.bind(this,myArg) 3. /调用方式 4. this.addContent(myArg,xmlhttp) 5. 6. 7. /用bindAsEventListener方法 8. this.addContent.bindAsEventListener(this,myArg) 9. /调用方式 10. this.addContent(xmlhttp,myArg) 第二步,实现静态模板类StaticTemplate。对于静态模板,其显示过程是这样的:向服务器发起一次异步请求,返回所有分页数据,服务器按照客户 设定的每页显示数量来生成所有页,一次新传回客户端。每一页由一对tbody元素定义,然后通过css类名来讲所有的页面隐藏,最后由客户端js来控制显 示页面,初始显示第一页。服务器返回的数据格式如下(只要结构一样就可以了,没有行、列数目的限制,这可以参看前一篇文章中的css设定了解,是可以随表 格大小伸缩的),总条目数为6,分了两页:xml 代码1. 2. 静态分页模板 3. 4. 5. 标题一 6. 标题二 7. 标题三 8. 标题四 9. 标题五 10. 标题六 11. 12. 13. 14. 15. 1 16. 1 17. 1 18. 1 19. 1 20. 1 21. 22. 23. 2 24. 2 25. 2 26. 2 27. 2 28. 2 29. 30. 31. 3 32. 3 33. 3 34. 3 35. 3 36. 3 37. 38. 39. 4 40. 4 41. 4 42. 4 43. 4 44. 4 45. 46. 47. 48. 49. 50. 5 51. 5 52. 5 53. 5 54. 5 55. 5 56. 57. 58. 6 59. 6 60. 6 61. 6 62. 6 63. 6 64. 65. 66. StaticTemplate类中,addPage方法统计table中tbody元素的个数来确定总页数,并附加到对象上。以供 addNavigation方法成分页导航信息: js 代码1. this.pageTotal=this.wrap.getElementsByTagName(tbody).length; 在addNavigation方法中,又一次用到了前面提过的bindAsEventListener技巧,并通过切换css类名来达到突出显示当前页码 以及显示页面。具体的StaticTemplate代码实现如下:js 代码1. /* 2. *静态模板,一次请 求全部数据 3. */ 4. Tbi.StaticTemplate=Class.create(); 5. Tbi.StaticTtotype=Object.extend(newTbi.Template(), 6. 7. /* 8. *构造函数,实例化静态模板 9. *参数:父容器,每页显示条目数,数据获取地址 10. */ 11. initialize:function(wrap,items,catchUrl) 12. this._init(wrap,items,catchUrl); 13. this.mode=static; 14. , 15. 16. /实 现父类抽象方法,向页面添加默认分页 17. addPage:function(xmlhttp) 18. this.wrap.innerHTML=xmlhttp.responseText; 19. this.pageTotal=this.wrap.getElementsByTagName(tbody).length; 20. vartable=$(pages); 21. varpages=$A(table.getElementsByTagName(tbody); 22. displayPage=pages0; 23. displayPage.className=; 24. , 25. 26. /实 现父类抽象方法,向页面添加分页导航 27. addNavigation:function() 28. if(this.pageTotal1) 29. varnavigation=document.createElement(div); 30. navigation.id=navigation; 31. varcontext=this; 32. $R(1,this.pageTotal,false).each( 33. function(item) 34. varlink=document.createElement(a); 35. link.href=#; 36. link.onclick=context._changePage.bindAsEventListener(context,link); 37. link.appendChild(document.createTextNode(item); 38. if(item=1) 39. link.className=active; 40. 41. navigation.appendChild(link); 42. 43. ); 44. this.wrap.appendChild(navigation); 45. 46. , 47. 48. /导 航链接点击事件处理函数,切换页面内容,同时改变导航链接样式(突出显示当前页) 49. _changePage:function(event,link) 50. varactiveLink=$(#TMPwrapdivaclass=active)0; 51. if(activeLink!=link) 52. varpages=$(#TMPwraptbody); 53. varoldPage=pages.find( 54. function(item) 55. returnitem.className=; 56. 57. ); 58. varnewPage=pageslink.firstChild.nodeValue-1; /inner系列属性不兼容ff 59. oldPage.className=hidden; 60. newPage.className=; 61. activeLink.className=; 62. link.className=active; 63. 64. Event.stop(event); 65. 66. 67. ); 这样,我们就完成了静态分页模板的设计和实现,下一步是实现动态异步的两种获取方式模板。在前面两篇文章中,我们实现了静态表格分页模板,下面让我们继续讨论,如何实现另外两种数据获取方式的模板。要缓解服务器的压力,我们可以这样做:1、显示初始页面也就是第一页的时候,我们构造好表头、标题和第一页的数据,并按照服务器返回的总页数生成导航链接,之后将不再更新这部分重复的内容;2、对于每一页新内容,我们在点击页码链接的时候再动态向服务器获取数据,服务器根据所请求的页码返回特定页的内容,替换掉当前显示的页面数据,这样可以 减少网络带宽的使用,毕竟每次只返回一页的内容;3、对于数据更新频繁的分页系统,就按照上面的办法每次获取新数据;而对于不是很频繁的数据,我们提供一种客户端缓存机制来加快响应速度和减轻服务器压 力:通过一个全局的cache数组来存放服务器端之前返回的数据,在切换页面的时候,先查询缓存,如果没有命中,再向服务器发起异步请求,当响应到达的时 候,也会将此次数据存入缓存以供使用。按照上面的分析,可以发现这两种数据获取方式的模板有很多相似的地方,不同的只是缓存与否,我们可以将他们抽象成同一个类来实现,下面是 javascript代码,我将在后面就一些需要注意的地方做详细讲解: js 代码1. /* 2. *异步模板,每次请求一个页面,并缓存浏览过的页面(可选) 3. */ 4. varmixin=newTbi.StaticTemplate();/用于mixin(混入)对象方法addNavigation 5. Tbi.AsyncTemplate=Class.create(); 6. Tbi.AsyncTtotype=Object.extend(newTbi.Template(), 7. 8. initialize:function(wrap,items,catchUrl,option) 9. this._init(wrap,items,catchUrl); 10. this.mode=async; 11. /option为可选参数,设置初始显示页面以及是否缓存页面 12. this.option=Object.extend(isCache:true,option); 13. if(this.option.isCache) 14. this.cache=newArray();/缓存数组; 15. 16. , 17. 18. /实 现父类抽象方法,向页面添加默认分页 19. addPage:function(xmlhttp) 20. varoriginal=xmlhttp.responseText; 21. varhtml=original.stripScripts(); 22. this.wrap.innerHTML=html; 23. original.evalScripts(); 24. , 25. 26. /mixin(混 入)StaticTemplate类的同名方法,向页面添加分页导航 27. addNavigation:mixin.addNavigation,/方法劫 持,重用addNavigation添加分页导航 28. 29. /导 航链接点击事件处理函数,切换页面内容,同时改变导航链接样式(突出显示当前页) 30. _changePage:function(event,link) 31. varactiveLink=$(#TMPwrapdivaclass=active)0; 32. if(activeLink!=link) 33. link.className=active; 34. activeLink.className=; 35. this._displayPage(link); 36. 37. Event.stop(event); 38. , 39. 40. /根 据缓存标志切换页面内容 41. _displayPage:function(link) 42. varpage=link.firstChild.nodeValue; 43. /如果是第一页,且进行缓存的话,直接切换页面元素的可见性 44. if(page=1&this.cache) 45. $(default).className=; 46. $(swap).className=hidden; 47. 48. /否 则,根据缓存标志,切换显示其它页(包括非缓存的默认页) 49. else 50. $(default).className=hidden; 51. varoldPage=$(swap); 52. swapPage=this._prompt(正在获取数据); 53. $(pages).replaceChild(swapPage,oldPage); 54. this._showPage(page); 55. 56. , 57. 58. /显 示提示信息 59. _prom
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 46000-2025节水型企业木材加工及其制品行业
- 青岛邮政考试题库及答案
- 电信资源考试题库及答案
- 森林防火业务知识培训
- 森林灭火水泵培训知识课件
- 2025年无机化学反应生产高级专业技能面试题解析
- 2025年教育行业教师招聘面试技巧及模拟题解答手册
- 《机械员》考试题库附完整答案(典优)
- 2025江苏省安全员《B证》考试题库及答案
- 2025年公共经济理论与实践能力测试模拟题集及答案详解
- 勉县一中小升初数学试卷
- 2025一建《建设工程经济》计算、时间、数字考点笔记
- 校园基孔肯雅热防控措施课件
- 生猪屠宰兽医卫生检验人员理论考试题库及答案
- 实测实量测量表格优质资料
- 读书笔记 -《提高利润的78个方法》
- GB/T 14273-1993旋转轴唇形密封圈性能试验方法
- GB/T 12247-2015蒸汽疏水阀分类
- 期权风险管理课件
- 《护理伦理学》教学大纲(本科)
- 板带轧机刚度对热轧板形的影响
评论
0/150
提交评论