欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于在Ext.data.Model中使用mapping无效

程序员文章站 2022-05-13 14:12:08
...

先定义一个简单的Model:

Ext.define("ProductModel", {
	extend: "Ext.data.Model",
	fields: [
		{
			name: "product",
//			mapping: "p.name"  // 这种写法也可以,使用下面的function是为了调试
			mapping: function(data) {
//				alert(data.p.name);
				return data.p.name;
			}
		},
		{name: "sl", type: "int"}
	]
});

 上面的model很基础,没什么可说的。再创建一个Store:

var productStore = Ext.create("Ext.data.Store", {
	storeId: "productStore",
	model: "ProductModel",
	data: [{
		p: {
			name: "product1",
			brand: "b1"
		},
		sl: 11
	}, {
		p: {
			name: "product2",
			brand: "b2"
		},
		sl: 22
	}]
});

 最后是grid panel:

var productGP = Ext.create("Ext.grid.Panel", {
	border: false,
	store: productStore,
	columnLines: true,
	columns: {
		items: [
		    {xtype: "rownumberer", resizable: true},
		    {text: "产品", dataIndex: "product", flex: 1},
		    {text: "数量", dataIndex: "sl"}
		]
	}
});

 上述代码的本意是希望在grid panel的产品列中显示产品的名称,然而实际结果却是[Object Object]。经过调试发现,fields里面的mapping根本没起作用,这让我百思不得其解,求助google也没找到合适的答案。

正当心灰意冷时,我在extjs的api文档中发现端倪。首先请注意到我的store中使用了inline data,而在store的api文档中,Inline data小节有如下描述:

Loading inline data using the method above is great if the data is in the correct format already (e.g. it doesn't need to be processed by a reader). If your inline data requires processing to decode the data structure, use a MemoryProxy instead (see the MemoryProxy docs for an example).

 就是说,inline data是不会经过任何加工处理的,如果要对数据进行加工,可考虑使用MemoryProxy。

 好的,对上述代码进行改造,为store添加一个MemoryProxy:

var productStore = Ext.create("Ext.data.Store", {
	storeId: "productStore",
	model: "ProductModel",
	data: [{
		p: {
			name: "product1",
			brand: "b1"
		},
		sl: 11
	}, {
		p: {
			name: "product2",
			brand: "b2"
		},
		sl: 22
	}],
        proxy: {
                type: "memory",
                reader: {
                        type: "json"
                }
        }
});

 这样一来,mapping就起作用了,gridpanel也如我们所预期的那样显示了产品名称。

但是实际应用中,数据一般都是通过向服务器请求获得的,而不是这样写死在代码中。我个人习惯定义一个方法,在方法中发送一个Ext.Ajax.request请求,该方法接受一个object参数,该参数将作为Ext.Ajax.request请求的params。需要加载/更新数据的时候调用这个方法。为了方便,在此我只贴出Ext.Ajax.request的代码,并且也只给出了success情况下的处理:

Ext.Ajax.request({
	url: getContextPath() + "/test/extMappingTest",  // 你的请求地址
        params: param,    // 请求参数
	reader: "json",
	actionMethods: {
		read: "POST"
	},
	success: function(response) {
		var resp = Ext.JSON.decode(response.responseText);    // 服务器返回的是json格式的字符串,这里将其解析为一个Object
		productStore.removeAll();    // 清除原有数据
		productStore.loadData(resp);
	}
});

上述代码的实际运行结果并没有达到我们的预期,gridpanel没有正确显示出产品名称,只显示出数量。通过调试可以发现,和一开始使用Inline data一样,mapping根本没起作用。不过既然我们已经有了经验,知道必须通过proxy加载数据才会经过mapping的处理,那我们就手动调用proxy好了。将Ext.Ajax.request修改如下:

Ext.Ajax.request({
	url: getContextPath() + "/test/extMappingTest",  // 你的请求地址
        params: param,    // 请求参数
	reader: "json",
	actionMethods: {
		read: "POST"
	},
	success: function(response) {
		var resp = Ext.JSON.decode(response.responseText);    // 服务器返回的是json格式的字符串,这里将其解析为一个Object
		productStore.removeAll();    // 清除原有数据
		var rs = productStore.getProxy().getReader().readRecords(resp);	// 如想Model中fields里的mapping生效,必须通过proxy处理数据
		productStore.loadRecords(rs.records);
	}
});

 至此,大功告成。