怎么在开发纯富客户端(RIA)应用的时候利用标签库(tab library)

如何在开发纯富客户端(RIA)应用的时候利用标签库(tab library)

原来做项目的时候,会使用Ajax来做一些页面动态功能,最典型的如auto complete。 还有一些小范围的数据保存之类的,基本上从来没有做过全页面的表单都用Ajax来保存的开发。要实现把页面上的所有数据都用Ajax保存不麻烦,麻烦在保存后怎么办。通常保存完数据后,我们都会刷新整个页面,到一个完全不同的页面去:比如,保存完一个订单后跳回订单查询页面。通常用javascript的时候,我们只用它来做一些页面的小范围的动态效果,比如点某些按钮后多出一些输入框之类。我们不想用javascript来写出这个页面,那会太复杂,太难维护。所以总的来说,我们会实用JSP来渲染整个页面,不管直接些HTML还是用些标签库;然后用javascript,结合Ajax来做一些局部动态效果。

有没有办法难够用JSP直接写HTML或者标签来布局整个页面,同时又能在利用上Ajax的好处,在各种操作中不要刷新整个页面呢? 下面是我的两个想法。先声明,这两种方式在Grails上都是可行的,我猜想在Spring MVC上也是可行的。但是不保证在所有框架,比如JSF,上可行。

一,Ajax返回HTML并将其插入页面中

  1. 浏览器第一次打开页面的时候,只把页面的头部,底部等所有页面都会共用的外框渲染出来
  2. Javascript和CSS等要共用的资源也在同时加载。图片等具体到不同页面不同的资源不需要加载
  3. 和特定页面相关的内容,使用一个空的DIV之类的先占位
  4. 整体页面加载完后,根据具体页面的不同,前端用Ajax去后台二次加载局部页面。这个时候后台可以使用一个JSP模板,根据具体的模型渲染出一段HTML字符串,并返回。前端拿到这段HTML后将其插入预留的DIV中
  5. 局部页面特定的Javascript可以选择在第一次打开页面的时候加载,也可以选择在这个时候加载
  6. 如果页面需要变动,比如用户提交数据后我们要刷新都另外一个页面,那我们可以用javascript清除DIV的内容,再用Ajax去请求要显示的页面HTML,插入到DIV中

这种方式在第一次打开页面的时候显示的整体外框可以用JSP生成,后面用Ajax拿到的局部特定页面内容也可以用JSP生成;同时,除了第一次加载页面,后面的都是Ajax操作,保证不会刷新整个页面。

这种方式的不好在于,每次Ajax返回的都是HTML,这个Ajax操作的API通常不便于被其他功能使用。

二,让View和Controller,Model隔离

  1. Controller, Model不知道View的存在。 它不管调用Controller的是个JSP页面,还是一个Flash程序,或者甚至是iOS程序。Controller只负责处理数据并返回结果。这时候的Controller提供的就是一个单纯的API, 甚至可以做成Rest API。 参考:六步实现Rest风格的API
  2. 页面(View)还是由JSP来生成,这时候生成HTML的时候因为不存在特定的Model,所以会是一个包含大体结构的HTML,但是可能不是最终要呈现的。Grails里我们可以直接写一个GSP,然后URL直接写成GSP的路径即可让Grails帮忙生成不带Model输入的页面
  3. Javascript和CSS等资源要在这个时候加载
  4. 因为这个时候的HTML并没有包含特定的Model数据,所以需要预留对应的位置以备后面填充数据
  5. 页面加载完后用Ajax调用后台的action, 将返回的数据填入到页面中
  6. 如果页面需要变动,可以在第2步生成HTML的时候同时将这个时候要显示的HTML生成。改变页面的时候用javascript将一部分HTML隐藏,另外一部分显示即可。不需要将整个应用的所有页面的HTML都在一个View里生成,可以把一个模块的一系列页面,比如订单创建,查找,查看,修改等页面放在一个View里,当用户在同一个模块里操作时不需要刷新页面。如果跳到其他模块,则可让浏览器打开另外一个URL,用刷新页面的方式显示另外一个模块的内容
这种方式的最大时Controller提供的API时共有的,它不管页面如何实现,页面尽可用JSP标签库生成HTML。如果页面要重构,甚至改变技术,Controller都不需要做改动。
这种方式的不好在于,放弃了用Model和JSP模板结合生成HTML的功能,需要自己将数据一个个填入合理位置;同时要合理规划好什么时候需要刷新页面,什么时候不需要刷新页面。


关键字:RIA, Ajax, 富客户端, Tab lib, 标签库