23、Ajax开发的陷阱与prototype.js工具包应用

Ajax开发的陷阱与prototype.js工具包应用

1. Ajax应用的潜在问题

1.1 错误处理

如果Ajax应用在某些条件下崩溃,至少应该向用户报告明显的错误,如无法创建 XMLHTTPRequest 对象实例。若应用过于复杂,无法自动恢复到非Ajax模式,可将用户重定向到非Ajax版本的应用。

可以使用HTML页面中的 <noscript> … </noscript> 标签检测JavaScript是否可用。示例代码如下:

<noscript>
JavaScript is not available in this browser.  <br />
Please go <a href="otherplace.htm">HERE</a> for
the HTML-only version.<br />
</noscript>

1.2 搜索引擎爬虫问题

搜索引擎通过爬虫程序收集网站信息。对于高度动态的网站,爬虫可能无法访问通过动态方式加载的内容,从而无法对其进行索引。使用Ajax可能会加剧这个问题,因为它倾向于在更少的页面中提供更多内容。

为解决此问题,应确保爬虫能够索引网站上所有相关内容的静态版本。可以提供一个超文本链接的网站地图,因为爬虫会跟随页面中嵌入的链接。

1.3 页面元素交互提示

如果设计不当,用户可能不清楚页面上哪些元素可以点击或交互。可以在整个应用中使用一致的样式来显示哪些页面元素会引发服务器请求或其他动态活动,类似于HTML页面中超文本链接的样式与普通文本不同。

还可以通过Tooltip样式的弹出窗口提供有关活动元素的说明和信息,特别是当点击活动链接会对应用状态产生重大影响时。

1.4 不适合使用Ajax的场景

虽然Ajax可以显著改善Web界面,但在很多情况下,使用Ajax会降低用户体验。例如,基于页面的界面隐喻对于某些网站的内容和风格已经足够,甚至更合适。文本类网站将主题方便地拆分为章节式页面,通过智能设计的超链接可能与添加Ajax功能一样有益。小型网站可能难以从Ajax界面中获得足够的好处来平衡额外代码和复杂性带来的成本。

1.5 安全问题

Ajax本身似乎不会带来设计Web应用时不存在的安全问题,但Ajax增强的应用往往包含更多客户端代码。由于客户端代码内容可被任何用户轻松查看,因此不应在其中透露敏感信息,包括用户名、密码和业务逻辑。应让服务器端脚本负责处理数据库连接等问题,并在服务器上验证数据后再进行重要处理。

1.6 跨平台测试

不同浏览器在实现JavaScript时表现不同,如Microsoft和非Microsoft浏览器在生成 XMLHTTPRequest 对象实例方面存在重大差异,DOM处理和CSS实现也有许多细微差别。因此,测试新应用在各种浏览器上的兼容性非常重要,尤其是在面对Ajax应用的复杂性时。应尽可能在不同平台和浏览器上测试应用。

1.7 编程陷阱

  • 浏览器缓存GET请求 :重复向同一URL发送GET请求时,响应可能来自浏览器缓存而非服务器,在Internet Explorer中此问题尤为明显。可以通过在请求的URL中添加随机元素来解决,如添加随机数或基于时间的数字。示例代码如下:
var url = "serverscript.php"+"?rand="+new Date().getTime();
  • 权限拒绝错误 :收到“Permission Denied”错误通常意味着违反了阻止 XMLHTTPRequest 对象进行跨域请求的安全措施。调用必须针对与调用脚本位于同一域的服务器程序,且要确保域名的书写方式完全一致。
  • 内容转义 :在构造GET或POST请求的查询时,要对可能包含空格或其他非文本字符的变量进行转义。示例代码如下:
http.open("GET", url + escape(idValue) + "&rand=" + myRandom, true);

2. prototype.js工具包介绍

2.1 引入prototype.js

prototype.js是一个流行的JavaScript库,包含一系列用于开发跨浏览器JavaScript例程的有用函数,尤其对Ajax提供了特定支持。可以从http://www.prototypejs.org/ 下载最新版本,在编写本文时,其版本为1.6.0。

在Web应用中引入该库很简单,只需在HTML文档的 <head> 部分添加以下代码:

<script src="prototype.js" Language="JavaScript" type="text/javascript"></script>

2.2 prototype.js的常用函数

  • $()函数 :是 getElementById() DOM方法的快捷方式。示例代码如下:
// 普通方式
var mydata = document.getElementById('someElementID');
// 使用$()函数
var mydata = $('someElementID');

$() 函数还可以接受多个元素ID作为参数,并返回一个包含相关元素值的数组。示例代码如下:

mydataArray = $('id1','id2','id3');

在这个例子中:
- mydataArray[0] 包含ID为 id1 的元素的值。
- mydataArray[1] 包含ID为 id2 的元素的值。
- mydataArray[2] 包含ID为 id3 的元素的值。

  • $F()函数 :当传入表单输入元素或其ID作为参数时,返回该表单输入字段的值。示例代码如下:
<input type="text" id="input1" name="input1">
<select id="input2" name="input2">
  <option value="0">Option A</option>
  <option value="1">Option B</option>
  <option value="2">Option C</option>
</select>
// 返回文本框的值
$F('input1');
// 返回下拉框当前选中选项的值
$F('input2');
  • Form对象 :prototype.js定义了一个Form对象,有几个简化HTML表单操作的有用方法。
    • getElements() 方法:返回表单输入字段的数组。示例代码如下:
inputs = Form.getElements('thisform');
- `serialize()`方法:将输入名称和值格式化为与URL兼容的列表。示例代码如下:
inputlist = Form.serialize('thisform');
- `Form.disable('thisform')`和`Form.enable('thisform')`分别用于禁用和启用表单。
  • Try.these()函数 :提供了一种方便的方式来封装异常处理方法,以提供跨浏览器的解决方案。示例代码如下:
return Try.these(
  function() {return new ActiveXObject('Msxml2.XMLHTTP')},
  function() {return new ActiveXObject('Microsoft.XMLHTTP')},
  function() {return new XMLHttpRequest()}
)

2.3 封装XMLHTTPRequest的Ajax对象

2.3.1 Ajax.Request

Ajax.Request 处理创建 XMLHTTPRequest 对象实例并发送正确格式请求的细节。调用方式如下:

var myAjax = new Ajax.Request( url, {method: 'post', parameters: mydata, onComplete: responsefunction} );

其中, url 定义要调用的服务器资源的位置, method 可以是 post get mydata 是包含请求参数的序列化字符串, responsefunction 是处理服务器响应的回调函数。

第二个参数使用JSON(JavaScript Object Notation)表示法构建,由一系列参数:值对组成。 onComplete 参数对应 XMLHTTPRequest readyState 属性值为4(完成)的情况,还可以使用 onLoading onLoaded onInteractive 指定在之前的阶段执行回调函数。还有其他可选参数,如 asynchronous:false 表示同步进行服务器调用,默认值为 true

2.3.2 Ajax.Updater

当需要用返回的数据更新页面元素时, Ajax.Updater 类可以简化任务。只需指定要更新的元素:

var myAjax = new Ajax.Updater(elementID, url, options);

示例代码如下:

<script>
function updateDIV(mydiv)
{
  var url = 'http://example.com/serverscript.php';
  var params = 'param1=value1&param2=value2';
  var myAjax = new Ajax.Updater(
    mydiv,
    url,
    {method: 'get', parameters: params}
  );
}
</script>
<input type="button" value="Go" onclick="updateDIV(targetDiv)">
<div id="targetDiv"></div>

还可以添加 evalscripts:true 选项,使服务器返回的任何JavaScript代码都能被执行。

2.3.3 Ajax.PeriodicalUpdater

Ajax.PeriodicalUpdater 类可用于重复创建 Ajax.Updater 实例,以在一定时间间隔后更新页面元素。它在股票行情显示器或RSS阅读器等应用中很有用。

Ajax.PeriodicalUpdater Ajax.Updater 选项的基础上增加了两个参数:
- frequency :连续更新之间的延迟时间(秒),默认值为2秒。
- decay :如果服务器返回未更改的数据,后续延迟增加的乘数,默认值为1,即延迟保持不变。

示例代码如下:

var myAjax = new Ajax.PeriodicalUpdater(elementID, url, {frequency: 3.0, decay: 2.0});

2.4 示例项目:股票价格阅读器

2.4.1 服务器端脚本

使用 rand.php 脚本模拟不断变化的股票价格:

<?php
srand ((double) microtime( )*1000000);
$price = 50 + rand(0,5000)/100;
echo "$price";
?>
2.4.2 HTML页面

构建一个简单的HTML页面来显示当前股票价格:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <script src="prototype.js" Language="JavaScript" type="text/javascript"></script>
  <title>Stock Reader powered by Prototype.js</title>
</head>
<body>
  <h2>Stock Reader</h2>
  <h4>Powered by Prototype.js</h4>
  <p>Current Stock Price:</p>
  <div id="price"></div>
</body>
</html>
2.4.3 实现Ajax.PeriodicalUpdater

Ajax.PeriodicalUpdater 类附加到文档主体元素的 onLoad 事件处理程序中:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <script src="prototype.js" Language="JavaScript" type="text/javascript"></script>
  <script>
    function checkprice()
    {
      var myAjax = new Ajax.PeriodicalUpdater('price', 'rand.php', {method: 'post', frequency: 3.0, decay: 1});
    }
  </script>
  <title>Stock Reader powered by Prototype.js</title>
</head>
<body onLoad="checkprice()">
  <h2>Stock Reader</h2>
  <h4>Powered by Prototype.js</h4>
  <p>Current Stock Price:</p>
  <div id="price"></div>
</body>
</html>

通过使用prototype.js,应用的代码变得非常简单,只需定义一个单行函数 checkprice() 来实例化重复的Ajax调用,并从主体元素的 onLoad 事件处理程序中调用该函数。

综上所述,在使用Ajax开发时,需要注意各种潜在问题,同时可以利用prototype.js工具包来简化开发过程,提高开发效率。

下面是一个简单的mermaid流程图,展示了 Ajax.PeriodicalUpdater 的工作流程:

graph TD
    A[开始] --> B[创建Ajax.PeriodicalUpdater实例]
    B --> C{设定时间间隔}
    C --> D[发送请求]
    D --> E{服务器返回数据}
    E -- 数据变化 --> F[更新页面元素]
    E -- 数据未变化 --> G{根据decay调整时间间隔}
    G --> C
    F --> C

在开发过程中,还可以通过以下表格总结不同函数和对象的功能:
| 函数/对象 | 功能 |
| — | — |
| $() | 简化获取元素值的操作 |
| $F() | 获取表单输入字段的值 |
| Form对象 | 简化HTML表单操作 |
| Try.these() | 封装异常处理方法 |
| Ajax.Request | 处理请求发送 |
| Ajax.Updater | 更新页面元素 |
| Ajax.PeriodicalUpdater | 定时更新页面元素 |

3. 总结与建议

3.1 开发要点回顾

在使用Ajax进行开发时,需要注意以下几个关键要点:
1. 错误处理 :确保在Ajax应用崩溃时能向用户报告明显错误,复杂应用可考虑重定向到非Ajax版本。
2. 搜索引擎友好 :为搜索引擎爬虫提供静态版本内容和超文本链接的网站地图。
3. 用户交互提示 :使用一致样式和Tooltip弹出窗口明确页面活动元素。
4. 适用场景判断 :评估是否适合使用Ajax,避免在不适合的场景增加复杂度。
5. 安全问题 :不在客户端代码中透露敏感信息,让服务器端处理关键业务逻辑。
6. 跨平台测试 :在多种浏览器和平台上测试应用,确保兼容性。
7. 编程陷阱处理 :处理浏览器缓存、权限拒绝和内容转义等问题。

3.2 prototype.js工具包优势

prototype.js工具包为Ajax开发提供了诸多便利,其主要优势如下:
- 简化代码 :通过快捷函数和对象封装,减少了开发过程中的代码量,提高了代码的可读性和可维护性。
- 跨浏览器支持 :提供了跨浏览器的解决方案,如 Try.these() 函数处理不同浏览器的 XMLHTTPRequest 对象创建。
- 表单处理 Form 对象的方法简化了HTML表单的操作,如序列化表单数据。
- 请求处理 Ajax 对象的不同类封装了请求发送、响应处理和页面更新等功能,使开发人员无需关注底层细节。

3.3 开发建议

  • 谨慎使用Ajax :在决定是否使用Ajax时,要充分考虑应用的实际需求和场景,避免过度使用导致用户体验下降。
  • 遵循最佳实践 :在编写代码时,遵循良好的编程习惯,如注释代码、验证数据和使用合适的命名规范。
  • 持续测试 :不断在不同环境中测试应用,及时发现并解决兼容性和性能问题。
  • 利用工具包 :合理利用prototype.js等工具包,提高开发效率和代码质量。

4. 常见问题解答

4.1 为什么我的Ajax请求总是返回缓存数据?

这可能是因为浏览器缓存了之前的请求响应。可以通过在请求的URL中添加随机元素来解决,例如:

var url = "serverscript.php"+"?rand="+new Date().getTime();

4.2 我收到了“Permission Denied”错误,该怎么办?

这个错误通常意味着你违反了跨域请求的安全限制。确保你的请求是针对与调用脚本位于同一域的服务器程序,并且域名的书写方式完全一致。

4.3 如何在prototype.js中处理表单数据?

可以使用 Form 对象的方法来处理表单数据。例如,使用 getElements() 方法获取表单输入字段的数组,使用 serialize() 方法将表单数据格式化为URL兼容的字符串:

// 获取表单输入字段数组
var inputs = Form.getElements('thisform');
// 序列化表单数据
var inputlist = Form.serialize('thisform');

4.4 如何定时更新页面元素?

可以使用 Ajax.PeriodicalUpdater 类来定时更新页面元素。以下是一个示例:

var myAjax = new Ajax.PeriodicalUpdater('elementID', 'url', {frequency: 3.0, decay: 1});

5. 总结

通过本文的介绍,我们了解了Ajax开发中可能遇到的各种问题以及如何使用prototype.js工具包来简化开发过程。在实际开发中,要充分考虑应用的需求和场景,合理使用Ajax技术,并遵循最佳实践,以提高开发效率和用户体验。

以下是一个总结表格,展示了Ajax开发的关键要点和prototype.js的主要功能:
| 类别 | 要点 | 说明 |
| — | — | — |
| Ajax开发要点 | 错误处理 | 向用户报告错误,复杂应用可重定向 |
| | 搜索引擎友好 | 提供静态内容和网站地图 |
| | 用户交互提示 | 使用一致样式和Tooltip |
| | 适用场景判断 | 避免过度使用 |
| | 安全问题 | 保护敏感信息 |
| | 跨平台测试 | 在多种环境中测试 |
| | 编程陷阱处理 | 处理缓存、权限和转义问题 |
| prototype.js功能 | 快捷函数 | $()、$F()简化操作 |
| | Form对象 | 简化表单处理 |
| | Try.these() | 跨浏览器异常处理 |
| | Ajax对象 | 封装请求和页面更新功能 |

下面是一个mermaid流程图,展示了使用prototype.js开发Ajax应用的基本流程:

graph TD
    A[引入prototype.js] --> B[定义页面元素]
    B --> C[处理表单数据]
    C --> D[发送请求]
    D --> E{服务器响应}
    E -- 成功 --> F[更新页面元素]
    E -- 失败 --> G[处理错误]
    F --> H[定时更新(可选)]
    G --> D

希望本文能帮助你更好地理解Ajax开发和prototype.js工具包的使用,在实际项目中取得更好的效果。

【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)内容概要:本文介绍了基于蒙特卡洛和拉格朗日方法的电动汽车充电站有序充电调度优化方案,重点在于采用分散式优化策略应对分时电价机制下的充电需求管理。通过构建数学模型,结合不确定性因素如用户充电行为和电网负荷波动,利用蒙特卡洛模拟生成大量场景,并运用拉格朗日松弛法对复杂问题进行分解求解,从而实现全局最优或近似最优的充电调度计划。该方法有效降低了电网峰值负荷压力,提升了充电站运营效率经济效益,同时兼顾用户充电便利性。 适合人群:具备一定电力系统、优化算法和Matlab编程基础的高校研究生、科研人员及从事智能电网、电动汽车相关领域的工程技术人员。 使用场景及目标:①应用于电动汽车充电站的日常运营管理,优化充电负荷分布;②服务于城市智能交通系统规划,提升电网交通系统的协同水平;③作为学术研究案例,用于验证分散式优化算法在复杂能源系统中的有效性。 阅读建议:建议读者结合Matlab代码实现部分,深入理解蒙特卡洛模拟拉格朗日松弛法的具体实施步骤,重点关注场景生成、约束处理迭代收敛过程,以便在实际项目中灵活应用改进。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值