ExtJs之数据和ComboBox控件
一、如何获取数据
在ExtJs中获取数据主要靠下面四个类: Ext.data.DataProxy、Ext.data.Record、Ext.data.DataReader、Store。下面对这三个类做个简单的介绍。
DataProxy:获取想要的数据。通过他能得到来自不同地方的数据,如数组、远程服务器,并组织成不同的格式。
DataReader:定义数据项的逻辑结构,一个数据项有很多列,每列的名称是什么,分别是什么数据类型,都由该类来定义。另外,还负责对不同格式的数据进行读取和解析。在这里用到了Ext.data.Record类来定义具体的列类型。
Store:存储器,用于整合Proxy和Reader,控件索取数据时通常和他打交道。
二、Ext.data.DataProxy 类
proxy是代理的意思,很多时候,聪明的架构师和设计者为了屏蔽底层的差异,给用户提供一个统一的访问接口,会设计一个名为“proxy”的类。这种设计哲学在架构中普通应用,并且解决了很多实际问题,代码也变得更加优雅,并有效降低代码侵入。
Ext.data. DataProxy就是来源于这样一种灵感。
Ext.data.DataProxy 是获取数据的代理,数据可能来自于内存,可能来自于同一域的远程服务器数据,更有可能来自于不同域的远程服务器数据。
但是,在实际应用中,我们不会直接使用Ext.data.DataProxy,而是使用他的子类:MemoryProxy、HttpProxy和ScriptTagProxy,他们的作用分别是:
MemoryProxy:获取来自内存的数据,可以是数组、json或者xml。
HttpProxy:使用HTTP协议通过ajax 从远程服务器获取数据的代理,需要指定url。
ScriptTagProxy:功能和HttpProxy一样,但支持跨域获取数据,只是实现时有点偷鸡摸狗。
因为数据最终要显示在ComboBox 中,所以我们以ComboBox 为中心进行设计。大家应该知道,下拉列表框有两个值,一个是显示值,另一个是实际值,也就是说,一个数据项包含两列:显示值列和实际值列。我们定义一个用来保存城市名称的二维数组:
var cities = [["1", "沈阳"], ["2", "大连"], ["3", "鞍山"], ["4", "辽阳"]];
在二维数组中,每一个城市保存了两个值:值一表示城市编号,作为实际值,值二表示城市名称,作为显示值。然后,我们将data 构建出一个MemoryProxy对象:
var mp = new Ext.data.MemoryProxy(cities);
三、Ext.data.DataReader 类
DataReader 从来不是单独行动的,他没有太多的自主权,总是看DataProxy行事。总体来说,DataReader 用来定义数据项(行)的逻辑结构,主要信息有:列的逻辑名称(name)、列的数据类型(type)、列与数据源的索引映射(mapping)等,另外,还包含一些元数据,如分页信息。
实际上,每一个数据项都是一个Ext.data.Record(记录)对象,而数据项的列信息则是通过Ext.data.Record来定义的。Ext.data.Record并没有固定的结构,他保存的是一个json对象数组,数组的元素个数由列的数量来决定。在上面的例子中,城市包含ID 和名称,所以,必须在数组中定义两个元素,基本就是这个样子:
var myRecord = Ext.data.Record.create([{ name : 'cid', type : 'int', mapping : 0 }, { name : 'cname', type : 'string', mapping : 1 }]);
我们定义了一个myRecord的结构,通过Ext.data.Record.create创建,参数是一个json对象数组,name 和type 分别表示每一列的名称和数据类型,mapping 是列值与数组元素的映射关系。
Record 创建好后,必须和DataReader 关联,DataReader 也同样有三个子类:Ext.data.ArrayReader、Ext.data.JsonReader、Ext.data.XmlReader。我之前说过DataReader 从来不单独行动,使用哪一个子类主要取决于DataProxy中封装的数据类型,如果是数组,则使用Ext.data.ArrayReader;如果是json,则使用Ext.data.JsonReader;如果是xml,则使用Ext.data.XmlReader。
在本例中,我们处理的数据类型是数组,所以自然要使用ArrayReader。
var myReader = new Ext.data.ArrayReader({}, myRecord);
构造ArrayReader 对象时,构造函数的第一个参数就是元数据,第二个参数则是Record。也可以一步到位:
var myReader = new Ext.data.ArrayReader({}, [ {name: "cid", type: "int", mapping: 0}, {name: "cname", type: "string", mapping: 1} ]);
四、Ext.data.Store 类
这个类相对简单,不需要面对数据和结构,只是把DataProxy和DataReader 整合在一起,这样一来,数据有了,结构有了,俨然就是一张数据表,想一想数据库中的物理表是不是就是这样的呢?嗯,非常像。
典型的写法像这样:
var store = new Ext.data.Store({ proxy: proxy, reader: reader });
到了这一步,别以为大功告成了,其实这时候数据并没有加载到Store中,默认情况下,Store采取延时加载,必须显式调用load()方法,当然,我们也可以采取即时加载策略,按如下配置即可:
var store = new Ext.data.Store({ proxy: proxy, reader: reader, autoLoad: true //即时加载数据 });
我们画张图,用来描述这三个类之间的关系。
可以看出,Ext.data.Store的主要目的是在内存中建立一张数据表,填充到组件中,这些组件形态也千差万别,最典型的就是ComboBox 和GridPanel。
五、下拉列表框
下拉列表框被定义成ComboBox 类,位于Ext.form命名空间,和Button不同,他是一个表单域组件,常用于表单中。
我们有一个这样的ComboBox,该组件用来显示辽宁的城市。
看起来和select标记别无二致,只是更加漂亮了。
一起来熟悉一个比较典型的ComboBox的定义方法:
var combobox = new Ext.form.ComboBox({ renderTo : Ext.getBody(), triggerAction : "all", store : store, displayField : "cname", valueField : "cid", mode : "local", emptyText : "请选择辽宁城市" });
嘿嘿,如果不解释您一定会愣上半天,有时候真不习惯Extjs中属性名称的定义风格,也许只怪我们的头发太长见识太少,来认识一下吧。
triggerAction:是否开启自动查询的功能,为all表示不开启,为query表示开启,默认为query;
store:不用解释了,和前面的Ext.data.Store对象挂勾,定义数据源;
displayField:关联Record的某一个逻辑列名作为显示值,本例为城市名称;
valueField:关联Record的某一个逻辑列名作为实际值,本例为城市ID;
mode:可选值有local和remote,如果数据来自本地,用local,如果数据来自远程服务器,必须用remote,默认为remote;
emptyText:没有选择任何选项的情况文本框中的默认文字。
请理解并记住这个基本的用法,很多东西都是这样巩固消化的。当我们面对如海水般涌来的信息,第一感觉就是无所适从,继而惊惶失措,夺路而逃,于是被永远挡在真理的大门之外。成功和失败,只在一念之间。
抓住核心点之后,慢慢扩展,知识架构便会越来越丰满,因为把握好了整个知识点的精髓,再怎么变化,都不至于迷路。
六、得到下拉列表框的值
下拉列表框(ComboBox)有两个值,显示值和实际值。显示值为用户提供了更为直观和理想的体验,而实际值则会传送到服务器,供服务器处理。
ComboBox定义了两个方法,其中,getValue()用于返回实际值,getRawValue()用于返回显示值。
我在页面上放置了一个按钮,点击按钮显示下拉列表框的值:
var btn = new Ext.Button({ text : "列表框的值", renderTo : Ext.getBody(), handler : function() { Ext.Msg.alert("值", "实际值:" + combobox.getValue() + ";显示值:" + combobox.getRawValue()); } });
七、源代码
下面是本章示例的源程序:
Ext.onReady(function() { cmp(); }); var cmp = function() { // 1. 定义本地静态数据 var cities = [["1", "沈阳"], ["2", "大连"], ["3", "鞍山"], ["4", "辽阳"]]; // 2. 根据数据定义内存代理 var mp = new Ext.data.MemoryProxy(cities); // 3. 创建记录格式 var myRecord = Ext.data.Record.create([{ name : 'cid', type : 'int', mapping : 0 }, { name : 'cname', type : 'string', mapping : 1 }]); // 4.把数据按照创建的记录格式进行组合 var myReader = new Ext.data.ArrayReader(mp, myRecord); //var reader = new Ext.data.ArrayReader({}, myRecord); // 5.把数据按照一定格式组成的数据组传入缓存 var myStore = new Ext.data.Store({ proxy : mp, reader : myReader, autoLoad : true }); // store.load(); 如果在Store配置信息中使用autoLoad:true,就可以不用此方法. // 5.创建下拉列表,把数组写入下接列表 var myCb = new Ext.form.ComboBox({ id : "myCb1", store : myStore, title : "辽宁省下属市", emptyText : "辽宁省下属市", displayField : "cname", valueField : "cid", triggerAction : "all", mode : "local", renderTo : Ext.getBody() }); // 6.创建按钮,实现读取下拉列表 var myBtn = new Ext.Button({ id : "myBtn1", type : "button", text : "所选城市", renderTo : Ext.getBody(), handler : function() { if (myCb.getValue() == "") { Ext.Msg.alert("提示","请做出选择"); myCb.focus(true); } else { Ext.Msg.alert("值", "实际值:" + myCb.getValue() + ";显示值:" + myCb.getRawValue()); } } }); }
下一篇: 关于PHP查询关联的两个表疑问
推荐阅读
-
[Asp.net之旅]--数据绑定控件之ListView
-
WinForm中comboBox控件数据绑定实现方法
-
C#预定义数据类型之值类型和引用类型介绍
-
android之视频播放系统VideoView和自定义VideoView控件的应用
-
数据挖掘之Apriori算法详解和Python实现代码分享
-
ASP.NET2.0中数据源控件之异步数据访问
-
python数据结构之图深度优先和广度优先实例详解
-
Extjs4如何处理后台json数据中日期和时间
-
前端笔记之微信小程序(二){{}}插值和MVVM模式&数据双向绑定&指令&API
-
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍