为什么用AJAX?
使用AJAX,用户对Web的体验会更“敏捷”:数据提交页面不会闪屏;页面局部更新速度快;网络带宽占用低。
AJAX开发相较传统模式的简单之处:
传统模式下,表单提交则整个页面重绘,为了维持页面用户对表单的状态改变,要多些不少代码。 要在控制器和模板之间传递更多参数以保持页面状态。而AJAX不然,因为页面只是局部更新, 不关心也不会影响页面其他部分的内容。
AJAX开发相较传统模式的难度:
需要了解、精通JavaScript,而JavaScript存在调试麻烦、浏览器兼容性等很多障碍。
Prototype是一个JavaScript框架,可以更加容易的使用AJAX实现动态Web。 Pylons内置了prototype脚本。如果想要启用Pylons自带prototype 的JavaScript框架,只要在模板中嵌入如下WebHelpers语句:
<html> <head> ${h.javascript_include_tag(builtins=True)}
实际上会在页面中产生下面两个JavaScrip包含语句:
<script src="/javascripts/prototype.js" type="text/javascript"></script> <script src="/javascripts/scriptaculous.js" type="text/javascript"></script>
改造之后的CGI(controller的action)不再返回整个页面, 而是返回局部的需要动态更新的内容,或者是返回一段数据供页面中的 JavaScript解析使用。
需要把原来返回一个整个页面的CGI(一个controller的一个方法)改造成多个CGI (多个方法)以针对不同情况返回不同的动态内容。
例如:pySvnManager的check控制器的submit方法实际上要处理两种情况: 一个是当选定一个版本库时要更新页面中的路径列表项(因为不同的版本库定义了不同的授权路径), 另外一个是按下“检查权限”按钮要进行的表单提交,显示用户授权信息。 将check控制器的submit方法改造为AJAX实现,就需要一分为二。
页面要动态更新的内容封装在一个DOM容器中;
页面提交修改为执行一个JavaScript函数,该函数调用Ajax.Updater或者Ajax.Request函数;
当点击权限检查(④)按钮,原来的实现是直接进行表单的提交, 修改之后为执行一段JavaScript代码。
文件 check/index.mako 中用WebHelpers.rails的form_remote_tag 快速创建了一个Ajax Form。
## AJAX Form <% context.write( h.form_remote_tag( html={'id':'main_form'}, url=h.url(action='access_map'), update=dict(success="acl_msg", failure="acl_error"), method='post', before='showNoticesPopup()', complete='hideNoticesPopup();'+h.visual_effect("Highlight", "acl_msg", duration=1), ) ) %>
出现在页面中,则是如下的代码:
<form action="/check/access_map" id="main_form" method="POST" onsubmit="showNoticesPopup(); new Ajax.Updater({success:'acl_msg', failure:'acl_error'}, '/check/access_map', {asynchronous:true, evalScripts:true, method:'post', onComplete:function(request) {hideNoticesPopup(); new Effect.Highlight("acl_msg",{duration:1}); }, parameters:Form.serialize(this)}); return false;">
说明
当Form提交会执行onSubmit部分的代码,而不去执行Form action,因为onSubmit返回false;
Ajax.Updater的参数success,是成功执行后用返回信息填充的DOM容器;failure则相反;
'/check/access_map'是Ajax要执行的服务器CGI,其返回结果将用于填充相应的DOM容器;
onComplete是成功执行Ajax.Updater代码后要执行的JavaScript代码;
showNoticesPopup():弹出窗口,提示用户Ajax正在执行过程中,避免用户重复点击;
hideNoticesPopup():在Ajax执行完毕,关闭Ajax正在运行的提示窗口;
Effect.Highlight()是 scriptaculous.js提供的特效,闪烁更新的区域以引起注意;
parameters是用于传递参数,这里把整个表单的数据提交;
当从版本库下拉框(②)选择时,将触发更新授权路径的列表(③)。 原来的实现是提交整个表单并刷新整个页面,用AJAX改造后, 只更新授权路径的列表(③)部分。
虽然也可以用Ajax.Updater来更新整个授权路径列表,但为了演示另外一种Ajax处理方式, 以及获得更少的带宽占用和更快的响应,使用Ajax.Request来实现。
版本库下拉框(②)更新时,执行JavaScript函数:update_path(),而非提交表单:
<input type="radio" name="reposinput" value="select" Checked onClick="update_path(this.form)">
函数update_path(),执行Ajax.Request,从"get_auth_path"这个action获取信息, 并用返回值(request.reponseText)为参数调用JavaScript函数ajax_update_path。
function update_path(form) { var repos = ""; if (form.reposinput[0].checked) { repos = form.reposselector.options[form.reposselector.selectedIndex].value; } else { repos = form.reposname.value; } var params = {repos:repos}; showNoticesPopup(); new Ajax.Request( '${h.url_for(controller="check", action="get_auth_path")}', {asynchronous:true, evalScripts:true, method:'post', onComplete: function(request) { hideNoticesPopup(); ajax_update_path(request.responseText);}, parameters:params }); }
函数ajax_update_path(),解析参数code,更新授权路径的下拉列表框。 本例非常简单,直接将参数(code)当作JavaScript代码并执行(eval函数), 这是因为Ajax.Request获取到的内容是字符串格式的JavaScript代码。 最终这些JavaScript代码在函数ajax_update_path中被执行, 并用相应的数据更新了授权路径的列表(③)。
function ajax_update_path(code) { var id = new Array(); var name = new Array(); var total = 0; pathselector = document.forms[0].pathselector; lastselect = pathselector.value; pathselector.options.length = 0; try { eval(code); for (var i=0; i < total; i++) { pathselector.options[i] = new Option(name[i], id[i]); if (id[i]==lastselect) pathselector.options[i].selected = true; } } catch(exception) { alert(exception); } }
Copyright © 2006 WorldHello 开放文档之源 计划 |