话说Ajax访问WebSerivce 那都是说到烂的话题了,但你别真别说,当 Extjs4 遇上WebSerivce 还真是让人够折腾。
首先ExtJS 并没有可以直接访问WebSerivce 的Store或者说proxy,因此你得先自己定义一个:
2 extend: 'Ext.data.proxy.Ajax',
3 require: 'Ext.data',
4
5 buildRequest: function(operation) {
6 var params = Ext.applyIf(operation.params || { }, this.extraParams || { }),
7 request;
8 params = Ext.applyIf(params, this.getParams(params, operation));
9 if (operation.id && !params.id) {
10 params.id = operation.id;
11 }
12 //debugger;
13 //就是增加这一行
14 params = Ext.JSON.encode(params);
15 request = Ext.create('Ext.data.Request', {
16 params: params,
17 action: operation.action,
18 records: operation.records,
19 operation: operation,
20 url: operation.url
21 });
22 request.url = this.buildUrl(request);
23 operation.request = request;
24 return request;
25 },
27 'Content-Type': 'application/json; charset=utf-8'
28 },
29 actionMethods: {
30 create: 'POST',
31 destroy: 'DELETE',
32 read: 'POST',
33 update: 'POST'
34 }
35 });
现在好了,有了自己的proxy,可以访问webService了,接着上我们的Store
2 extend: 'Ext.data.TreeStore',
3 nodeParam: 'addressId',
4 proxy: Ext.create('Ext.ux.WebServiceAjaxProxy', {
5 url: 'WebService/CameraService.asmx/GetCameraAddress',
6 extraParams: {
7 },
8 reader: {
9 type: 'json',
10 root: 'd'
11 }
12 })
13 });
再定义一个Ext.tree.panel
2 extend: 'Ext.tree.Panel',
3 store: Ext.create('Ext.data.CameraTreeStore', {}),
4
5 height: '100%',
6 useArrows: true,
7 rootVisible: false,
8 isChecked: [false, false],
9 enableDD: true,
10 root: { text: '列表', id: "" },
11
12 initComponent: function() {
13 var me = this;
14
15 me.callParent(arguments);
16 }
17 });
可能兄弟你会问:到此,大功告成了吧?有什么好难的?不就是定义了自己的一个proxy? 嘿,事件还没完呢,服务器返回的的数据大概是这样子:
你猜这树会是什么样子?竟然是这样:
我这想想啊,这文字显示不出来到底是哈个子原因呢?看样子应该是没有text字段或者该字段为空吧?但我明明是有的啊,好吧,看来只能调试源代码了,折腾了半天终于找到了:
坑爹啊,data.d竟然还是字符串呢,怪不得,但Extjs为何不提示我?这异常处理也做得太不全了吧。行,那只能手工把它再JSON化了。
重写Ext.decode ,参考了jquery的做法的
2 if (typeof data !== "string" || !data) {
3 return null;
4 }
5 var rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
6 data = (data || "").replace(rtrim, "");
7
8 if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
9 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
10 .replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
11
12 // Try to use the native JSON parser first
13 var d = window.JSON && window.JSON.parse ?
14 window.JSON.parse(data) :
15 (new Function("return " + data))();
16 //关键是这一点:
17 if (Ext.isString(d.d)) {
18 d.d = Ext.decodeWS(d.d)
19 }
20
21 return d;
22 } else {
23 throw "Syntax error, unrecognized expression: Invalid JSON: " + data;
24 }
25 };
26 Ext.decode = Ext.decodeWS;
到了这一步,嘿,可爱的树终于出来了,大松一口气啊。可是真的高兴得太早了,当点击展开树的时候,EXTJS马上跳出
折腾啊,FUUUUUUUUUUUUUUUUUUUUUUUUUUU Y.................................................................................
好吧,经过各种苦逼的折腾,终于明白为哈了,就因为id,id绝对不可以是数字,如果是数字,那就把它当字符串那样返回:
看清楚了,id的值都是1,但有引号和没有引号是不一样,一定要有引号。
OK,写完了,乱乱的,总结一下:
1、Extjs请求Webservice首先要在请求的proxy中反序列化参数,并且设置请求头为'application/json; charset=utf-8',这样才可以返回json数据。
2、返回的数据只进行带一次json化是不行的,因为我们需要的数据都包含在data.d里,而进行一次json化d还是字符串,必须对d进行json化。
3、如果返回的数据有id的话,一定不可以设置为数字,需要用引号把它包起来当成字符串。
好了,就写这么大,如果有更好的实现办法望赐教!