ExtJs学习笔记(23)-ScriptTagProxy+XTemplate+WCF跨域取数据
ajax应用中跨域一直是一个非常麻烦的问题,目前也有一些解决办法,但要么比较麻烦,要么就不具备通用性,幸好ExtJs里的ScriptTagProxy提供了跨域读取数据的功能,而且在几大浏览器上都可以正常运行,但在使用过程中要注意几点:
1.服务端返回时,必须按以下格式返回:
stcCallback1001({...})
其中stcCallback1001中的1001是自动生成的,如果是分页提交的话,每再请求一次1001会变成1002,1003...类推
2.ExtJs官方的示例中虽然ScriptTagProxy的例子并不少,但是就是没有XTemplate+ScriptTagProxy跨域读取的单一功能示例,下面给一个XTemplate跨域读取数据的示例
a.服务端WCF的处理
Code
[OperationContract]
[WebInvoke(ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetData3?start={start}&limit={limit}&callback={callback}", Method = "*")]
public Stream GetData3(int start, int limit,string CallBack)
{
System.Threading.Thread.Sleep(1000);//为演示Ajax加载效果,停1秒
List<T_GuestBook> _List = new List<T_GuestBook>();
_List.Add(new T_GuestBook() { F_ID = 1, F_IP = "192.23.37.41", F_Date = DateTime.Now, F_Content = "这是第一条留言", F_Reply = "" });
_List.Add(new T_GuestBook() { F_ID = 2, F_IP = "192.168.0.1", F_Date = DateTime.Now, F_Content = "这是第二条留言", F_Reply = "" });
_List.Add(new T_GuestBook() { F_ID = 3, F_IP = "192.168.0.2", F_Date = DateTime.Now, F_Content = "这是第三条留言", F_Reply = "" });
_List.Add(new T_GuestBook() { F_ID = 4, F_IP = "172.168.235.1", F_Date = DateTime.Now, F_Content = "这是第四条留言", F_Reply = "" });
_List.Add(new T_GuestBook() { F_ID = 5, F_IP = "10.200.30.4", F_Date = DateTime.Now, F_Content = "这是第五条留言", F_Reply = "" });
_List.Add(new T_GuestBook() { F_ID = 6, F_IP = "10.200.30.5", F_Date = DateTime.Now, F_Content = "这是第六条留言", F_Reply = "" });
//以上操作也可以改为利用Linq直接从数据库读取
PageData<List<T_GuestBook>> _PageData = new PageData<List<T_GuestBook>>();
_PageData.RecordCount = _List.Count;
int PageSize = limit;
if (PageSize <= 0) { PageSize = 1; }
if (PageSize > _PageData.RecordCount) { PageSize = _PageData.RecordCount; }
_PageData.PageSize = PageSize;
//计算总页数
if (_PageData.RecordCount % _PageData.PageSize == 0)
{
_PageData.PageCount = (_PageData.RecordCount / _PageData.PageSize);
}
else
{
_PageData.PageCount = (_PageData.RecordCount / _PageData.PageSize) + 1;
}
int PageIndex = (start/limit) + 1;
if (PageIndex <= 0) { PageIndex = 1; }
if (PageIndex > _PageData.PageCount) { PageIndex = _PageData.PageCount; }
_PageData.CurrentPageIndex = PageIndex;
List<T_GuestBook> _List2 = _List.Skip(start).Take(limit).ToList();//取得当前页数据
_PageData.Data = _List2;
string returnStr = CallBack + "(" + JavaScriptConvert.SerializeObject(_PageData) +")";
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
sw.AutoFlush = true;
sw.Write(returnStr);
ms.Position = 0;
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return ms;
}
这里与上一篇http://www.cnblogs.com/yjmyzz/archive/2008/09/10/1288399.html (ExtJs学习笔记(22)-XTemplate + WCF 打造无刷新数据分页)相比,多了一个参数callBack,同时返回类型改为Stream,返回方法的处理参考了老张的(再说ExtJs与WCF之间的跨域访问)一文
b.ExtJs的前端处理
Code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link type="text/css" rel="Stylesheet" href="../resources/css/ext-all.css" />
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-all-debug.js"></script>
<style type="text/css"> *{font-size: 9pt;line-height: 120%;} .red{color: Red;} h1{font-size:16px;} </style>
</head>
<body>
<script type="text/javascript">
Ext.onReady(function() {
var proxy = new Ext.data.ScriptTagProxy({
url: 'http://ext.cneds.net/WCF/MyService.svc/GetData3'
//服务端的返回值类似:
//stcCallback1001({"RecordCount":6,"PageSize":2,"PageCount":3,"CurrentPageIndex":2,"Data":[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":new Date(1221399073843),"F_Content":"这是第三条留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":new Date(1221399073843),"F_Content":"这是第四条留言","F_Reply":""}]})
//其中stcCallback1001中的1001是自动生成的,如果是分页提交的话,每再请求一次1001会变成1002,1003类推
});
var reader = new Ext.data.JsonReader(
{ root: 'Data', totalProperty: 'RecordCount' },
[
{ name: 'F_ID' },
{ name: 'F_IP' },
{ name: 'F_Date' },
{ name: 'F_Content' }
]
);
var tpl = new Ext.XTemplate(
'<table width="100%">',
'<tpl for="data">', //表明这里开始循环
'<tr><td style="font-weight:bold;color:#666">网友[{F_IP}] {F_Date} 说:</td></tr>', '<tr><td> {F_Content}</td></tr>', '<tr><td><hr style="height:1px"/></td></tr>',
'</tpl>', //循环结束
'</table>'
);
var oGrid = Ext.get("page-grid");
//回调函数
function callback(data, arg, success) {
if (success) {
var _returnStr = Ext.util.JSON.encode(data);
//{"success":true,"records":[{"id":1001,"data":{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"这是第三条留言"},"json":{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"这是第三条留言","F_Reply":""}},{"id":1002,"data":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:28:28","F_Content":"这是第四条留言"},"json":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:28:28","F_Content":"这是第四条留言","F_Reply":""}}],"totalRecords":6}
//服务端将返回类似上面的字符串,无法直接跟xTemplate绑定,需要转换一下
var oReg = /"json":({.*?})/gi;
var oResult = _returnStr.match(oReg);
var s = "";
for (var i = 0; i < oResult.length; i++) {
oResult[i].match(oReg);
s += RegExp.$1 + ",";
}
if (s.length != 0) { s = s.substr(0, s.length - 1); }
s = "{data:[" + s + "]}";
//最终将转换成
//{data:[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:29:55","F_Content":"这是第三条留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:29:55","F_Content":"这是第四条留言","F_Reply":""}]}
var data = eval("(" + s + ")");
tpl.overwrite("page-grid", data);
}
}
oGrid.dom.innerHTML = "加载中";
proxy.load({ start: 2, limit: 2 }, reader, callback, this);
});
</script>
<div id="page-grid"></div>
</body>
</html>
这里要注意的是:
尝试了多次,发现XTemplate不支持多层节点的绑定,即服务端返回的值类似:
stcCallback1001({"RecordCount":6,"PageSize":2,"PageCount":3,"CurrentPageIndex":2,"Data":[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":new Date(1221399073843),"F_Content":"这是第三条留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":new Date(1221399073843),"F_Content":"这是第四条留言","F_Reply":""}]})
在回调函数里经过Ext.util.JSON.encode(data)处理后,变成了
{"success":true,"records":[{"id":1001,"data":{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"这是第三条留言"},"json":
{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"这是第三条留言","F_Reply":""}},{"id":1002,"data":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008
-09-14T21:28:28","F_Content":"这是第四条留言"},"json":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:28:28","F_Content":"这是第四条留
言","F_Reply":""}}],"totalRecords":6}
虽然也是标准的JSON字符串,但是数据节点是多层次的,XTemplate无法直接读取。所以只能在客户端用JS的正则表达式处理,手动重新组织成XTemplate所需的JSON对象,最终转换成:
{data:[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:29:55","F_Content":"这是第三条留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:29:55","F_Content":"这是第四条留言","F_Reply":""}]}
- mysql DUPLICATE KEY UPDATE 问题
- mysql复制学习二 安装及首次复制配置
- 关于操作权限
- hadoop loadBalance源码分析
- writeup | 应该不是 XSS
- Hbase 源码分析之 Get 流程及rpc原理
- MOCTF WEB 题解
- HBase行锁与MVCC分析
- HBase行锁探索
- Spring Cloud构建微服务架构:分布式服务跟踪(抽样收集)【Dalston版】
- HBase client访问ZooKeeper获取root-region-server DeadLock问题(zookeeper.ClientCnxn Unable to get data of zn
- zookeeper学习系列:四、Paxos算法和zookeeper的关系
- 有了phonegap你还android吗?
- zookeeper学习系列:三、利用zookeeper做选举和锁
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python字典-增、删、改
- C# dotnet 使用判断文件夹存在的方法判断一个文件路径会怎样
- 怎样给wordpress网站模板,添加最新文章、随机文章、热评文章?
- [医疗信息化][DICOM教程]1.使用Java的DICOM基础-理解DICOM文件-DICOM Basics using Java - Making Sense of the DICOM File
- python自动播放网课
- Istio实战——流量管理
- WordPress移除head头部js、css、feed等多余加载项
- python控制鼠标键盘,解放你的双手~
- 用腾讯云批量计算(batch-compute)调度GPU分布式机器学习
- R语言模拟保险模型中分类器的ROC曲线不良表现
- Linux xargs grep zgrep命令
- r语言空间可视化绘制道路交通安全事故地图
- 小知识:Oracle RAC添加服务名实现单节点访问
- Python去掉图片四周纯色边框
- R语言空间可视化:绘制英国脱欧投票地图