一般动作
登录
Wiki: BROPEN ▼: Document Index
»
Space: FAQ ▼: Document Index
»
Page: Sencha Touch 中，如何开发 nestedList 查询功能
搜索
zh
页面动作
导出 ▼: 以PDF格式导出 以RTF格式导出 以HTML格式导出
更多动作 ▼: 打印预览 察看源码
欢迎进入Wiki » FAQ » Sencha Touch 中，如何开发 nestedList 查询功能?

# Sencha Touch 中，如何开发 nestedList 查询功能?

在2014-01-07 11:17上被李小翔修改
评论 (0) · 附件 (1) · 记录 · 信息

Touch中，定义了一个通讯录的面板，面板中包含了一个 nestedList，同时还定义了一个 TreeStore，通过ajax的方式加载远程数据并显示，代码片段如下：

// 定义通讯录面板
Ext.define('MyApp.view.AddressPanel', {
extend: 'Ext.Panel',
config: {
itemId: 'addressPanel',
items: [
{
xtype: 'nestedlist',
store: 'AddressJsonTreeStore',
title: '通讯录',
...
}, ...
], ...
}, ...
};
// 定义 TreeStore
Ext.define('MyApp.store.AddressJsonTreeStore', {
extend: 'Ext.data.TreeStore',
config: {
model: 'MyApp.model.AddressModel',
storeId: 'AddressJsonTreeStore',
proxy: {
type: 'ajax',
url: 'address',
reader: {
type: 'json'
}
}, ...
}, ...
});

现在，需要在这个面板的title bar上，添加一个查询框，以实现根据名称查询的功能，由于数据库比较大，并且都是延迟加载，因此仍然采用ajax的加载方式。

首先，我们在通讯录面板的title bar上添加一个查询框searchfield：

...
title: '通讯录',
toolbar: {
xtype: 'titlebar',
items: [
{
xtype: 'searchfield',
align: 'right',
itemId: 'seaerchAddressField',
maxWidth: '130px',
label: '',
placeHolder: ' 姓名..'
},...
]
}

添加了查询框后，界面如下图所示：

然后，修改控制器，添加查询和重置事件：

Ext.define('MyApp.controller.AddressController', {
extend: 'Ext.app.Controller',
config: {
refs: {
// 定义一个属性，便于使用
addressNestedList: 'addresspanel nestedlist[itemId=addressNestedList]',
...
},
control: {
// 定义两个事件
"addresspanel [itemId=seaerchAddressField]": {
action: 'onSeaerchAddressFieldAction', // 点击查询后的事件
clearicontap: 'onSeaerchAddressFieldClearicontap' // 点击重置图标后的事件
}, ...
}
},
/**
* 点击查询后的事件
*/
onSeaerchAddressFieldAction: function(textfield, e, eOpts) {
this.searchAction( textfield.getValue().trim() );
},
/**
* 点击重置图标后的事件
*/
onSeaerchAddressFieldClearicontap: function(textfield, e, eOpts) {
this.searchAction();
},
/**
* 执行查询或重置
*/
searchAction: function(val) {
......
}
});

上面的控制器代码中，关键就是下面那个 searchAction 方法，这里将执行查询操作：

- 方案1：TreeStore 有一个 remoteFilter 属性，设置为 true 后，可以调用其 filter 或 find 方法执行ajax查询。
  但是在实际测试中，这种方法的性能非常低下，基本不可用
- 方案2：每次查询时，重新创建一个新的 store 对象，并设置为 nestedList 的 store，执行ajax查询与重新渲染。
  这中方案执行效率相当高，最终的代码示例如下。

searchAction: function(val) {
if ( val ) {
val = val.replace(/['"\/\\\s]/g, '');
if ( val.length < 2 ) {
return Ext.Msg.alert("请输入至少两个字");
}
}
var list = this.getAddressNestedList();
var storeId = "AddressJsonTreeStore_" + val;
if ( !val ) { // 重置
store = Ext.getStore("AddressJsonTreeStore");
} else { // 搜索
store = Ext.getStore(storeId);
if ( !store ) {
// 不同的查询条件，后台返回的机构id必须不一样，否则可能显示后台数据中没有的机构节点
store = Ext.create("MyApp.store.AddressJsonTreeStore", { storeId: storeId });
store.getProxy().setExtraParam('find', val); // 设置远程查询参数
list.getStore().setAutoDestroy(true);
list.setEmptyText("没有找到您想要的数据！");
}
}
list.updateStore( store ); // 速度最快
list.setStore( store );
}

在上面的最终代码中，需要注意后台返回的查询结果 json 数据中，如果仍然为树形结构，那么每个节点（非叶子节点）的id建议保持不一样，例如：

- 不是查询时，有如下的结构：{ data:{id:'foo', name:'foobar', data:{...}}, ... }
- 则查询结果应为：{ data:{id:'bar', name:'foobar', data:{...}}, ... }

原因在于 nestedList 的渲染缓存，如：

- 点开节点foobar，可以看到子节点 foo 与 bar
- 查询后，如果返回结果中的节点foobar的id保持不变，且子节点只有foo了，但此时点开节点foobar，仍然会显示出节点 foo 与 bar，这显然是错误的
- 若查询的返回结果中的节点foobar的id设置为一个新的值，则点开节点foobar后，只会显示出一个foo子节点，这才是正确结果。

标签： Sencha Touch
在2014-01-07 11:17上被李小翔创建

- 评论 （0）
- 附件 （1）
- 记录
- 信息

# 快速链接

- 首页
- 新闻动态
- FAQ

Copyright © 2013 北京博瑞开源软件有限公司
京ICP备12048974号