| 
 | 
 
 本帖最后由 bacy001 于 2015-9-3 21:19 编辑  
 
ajaxget() 与 ajaxpost() 函数是 Discuz!X 系统前端部分很重要的函数,两者在整个源码中有几百处调用,是 Discuz!X 系统中最主要的 Ajax 实现。 
本文将详细介绍 ajaxget() 函数,下一篇将介绍 ajaxpost() 函数,本系列教程基于 Discuz!X3.2 版本介绍,相对与 X2.5 版本来说 Ajax 部分没有本质变化,有关 X2.5 部分的内容,可以参考: 
Discuz!X 源码分析之 ajaxget() 函数 
Discuz!X 源码分析之 ajaxpost() 函数 
 
1、函数简析 
在 X3.2 版本中,ajaxget() 函数的定义依旧是放在 common.js 文件中,但是实现实际功能的代码已经移动到 ajax.js 文件中,参见以下两段源码: 
- // Line:510, Common.js
 
 - function ajaxget(url, showid, waitid, loading, display, recall) {
 
 -         $F('_ajaxget', arguments, 'ajax');
 
 - }
 
  复制代码 而实现实际功能的代码位于 ajax.js 文件的第8行: 
- // Line:8, Ajax.js
 
 - function _ajaxget(url, showid, waitid, loading, display, recall) {
 
 - /* ... */
 
 - }
 
  复制代码 在 Common.js 中函数 $F() 的功能是动态加载 js 文件,第一个参数是目标 js 文件中将要调用的函数名,第二个参数是将要传递给被调用函数的参数,第三个函数指明将要加载的 js 文件名。而在 X2.5 以及以前版本,ajaxget 的执行部分是直接写在 Common.js 文件中。 
 
参数说明: 
url(必填),ajax 对象将要访问的服务端 url; 
showid(必填),ajax 对象获取到服务端返回值以后,用于显示返回值的 HTML 容器元素的 ID; 
waitid,ajax 对象执行过程中,用于显示等待信息的 HTML 容器元素的 ID,默认值等于 showid 的值; 
loading,ajax 对象执行过程中,用于显示在 waitid 所指向的 HTML 容器元素中的内容,默认值为“请稍后”; 
display,服务端信息返回后 showid 的 style.display 值,如果设置为'none',则信息将不会显示在页面上; 
recall,回调 js,即信息成功返回后将会执行的前端 js 函数名称; 
 
2、应用实例 
本教程所有实例均假设运行于 Discuz!X 插件当中。 
假设插件的 pluginid 为:test; 
则此插件的访问 URL 为:http://yourdomain/plugin.php?id=test 
插件主模块文件名:./source/plugin/test/test.inc.php 
插件模板主要页面:./source/plugin/test/template/test.htm 
 
2.1、实例一:在插件中使用 ajaxget() 从服务端获取文本内容,并显示在页面的指定区域; 
2.1.1、test.inc.php 中的代码: 
- <?php
 
  
- $act = $_GET['act'];
 
  
- switch ($act) {
 
 -         case 'ajaxgetstring':
 
  
  复制代码 2.1.2、主模板 test.htm 代码如下: 
- {template common/header}
 
  
- <a href="plugin.php?id=test&act=ajaxgetstring" onclick="ajaxget(this.href, 'strbox'); return false;">
 
 -         Click Me
 
 - </a>
 
 - <span id="strbox" style="color:red;"></span>
 
  
- {template common/footer}
 
  复制代码 2.1.3、代码运行流程 
2.1.3.1、浏览器上访问插件地址后,开始执行 test.inc.php 中的代码; 
首先判断 URL 是否包含参数 act,如果没有,则调用模板文件 test.htm; 
如果 act 值为 'ajaxgetstring',则在睡眠 2 秒后向客户端输出 FORMHASH 的值,并退出; 
 
 
2.1.3.2、模板文件中除包含 Discuz 默认的头部和尾部模板外(必须包含,特别头部模板中加载了 common.js 库),只有一个 <a> 标签 和 <span> 标签; 
其中 A 标签的 onclick 事件中调用了 ajaxget 函数,两个参数分别是 A 标签的 href 属性值和 SPAN 标签的 ID 值,意思是 ajaxget 将发送请求到 this.href,并将返回值显示在 SPAN 标签中; 
 
 
2.1.3.3、当点击页面上的 A 标签后,会立即进入 ajaxget 函数执行,函数体首先处理相关的参数,其中比较重要的是对 url 进行处理,代码如下: 
- var url = url + '&inajax=1&ajaxtarget=' + showid;
 
  复制代码 也就是说 ajaxget 会给传入的 url 加上两个参数 inajax 和 ajaxtarget,inajax 为 1 表示这是一个 ajax 请求,ajaxtarget 表示回显信息的 HTML 容器元素 ID;当服务端 Discuz 内核检测到参数 inajax 为真时会对输出到客户端的信息做特殊处理,主要表现在加载模板的时候;请回顾 test.inc.php 中输出 FORMHASH 的代码: 
-   include template('common/header');
 
 -                 echo FORMHASH;
 
 -                 include template('common/footer');
 
 
  复制代码 按代码理解,这里加载的应该是模板文件: common/header.htm 和 common/footer.htm;但实际上,因为 inajax 为真的原因,template() 函数实际加载的模板是: common/header_ajax.htm 和 common/footer_ajax.htm;这两者的区别是 header 和 footer 是标准的头部和尾部模板,而 header_ajax 和 footer_ajax 实际上是 xml 文件格式的头部和尾部, 因此实际输出的内容就变成: 
- <?xml version="1.0" encoding="'.CHARSET.'"?>
 
 - <root><![CDATA[FORMHASH]]></root>
 
  复制代码 只有按照这种格式输出的内容,才能被 ajaxget 客户端正确提取。 
 
2.1.3.4、A 标签 onclick 事件中在 ajaxget 调用后面的 return false; 是必须的,如果缺少了这个 return,点击 A 标签后会按照正常的非 ajax 调用访问 href 指向的 URL,因此必须返回 false,以阻止这种情况发生。 
 
2.2、实例二:在实例一的基础上加上回调 js,即客户端接收到返回信息后自动执行指定的 js 函数; 
2.2.1、修改 test.htm 中 A 标签 onclick 事件中 ajaxget 函数的参数,修改后代码如下: 
- ajaxget(this.href, 'strbox','strbox','Just Wait a Moment!','', ajaxget_recall)
 
  复制代码 参数对应关系如下: 
url => this.href, 
showid => 'strbox', 
waitid => 'strbox', 
loading => 'Just Wait a Moment!', 
display => '', 
recall => ajaxget_recall, 
 
 
2.2.2、在 test.htm 中增加 JS 函数 ajaxget_recall 的部分,参考代码如下: 
- <script>
 
 - function ajaxget_recall() {
 
 -         alert('ajaxget_recall');
 
 - }
 
 - </script>
 
  复制代码 
2.2.3、代码分析 
先看看 ajaxget 中新加的参数,其中 loading 表示 ajaxget 发送请求到等待返回值的过程中显示在 waitid 指向的 HTML 容器元素中的内容,默认显示中文“请稍等”,此例中将显示为:Just Wait a Moment! 
再看 recall,当 ajaxget 正确接收到服务端发回的返回值后就会调用 Js 函数 ajaxget_recall()。 
 
2.3、实例三:服务端返回值中直接包含 JS 脚本并执行; 
2.3.1、修改 test.htm 中 A 标签的 href 值,将 'ajaxgetstring' 替换成 'ajaxgetscript',参考代码如下: 
- {template common/header}
 
  
- <a href="plugin.php?id=test&act=ajaxgetscript" onclick="ajaxget(this.href, 'strbox'); return false;">
 
 -         Click Me
 
 - </a>
 
 - <span id="strbox" style="color:red;"></span>
 
  
- {template common/footer}
 
  复制代码 2.3.2、test.inc.php 中增加 'ajaxgetscript' 分支,参考代码如下: 
-  case 'ajaxgetscript':
 
  
-                 $str = <<<EOF
 
 - Will Alert: OMG!
 
 - <script reload="1">
 
 - function alertstr() {
 
 -         alert('OMG!');
 
 - }
 
 - alertstr();
 
 - </script>
 
 - EOF;
 
  
-                 include template('common/header');
 
 -                 echo $str;
 
 -                 include template('common/footer');
 
  
-                 exit;
 
 
  复制代码 2.3.3、本例与实例二功能类似,可以根据实际情况灵活选择。唯一一点区别在于,本例中 script 标签中包含一个 reload 属性,如果 reload 值为真,则代表此 script 可以在页面上多次执行,如果为假,则只有在 ajaxget 第一次在 showid 所指向的 HTML 容器中输出返回值时才执行,后续重复点击 A 标签将不会再执行 script 标签中的 JS 代码; 
 
本节完 
 |   
 
 
 
 |