Extjs学习笔记之九 数据模型(上)


Posted in Javascript onJanuary 11, 2010

Extjs的数据模型分为以下几个部分:

数据记录 Record
数据集合中的一个条记录,包括数据的定义和值。相当于实体类。
数据代理 Proxy
用来获取数据的代理。相当于Datasource。
数据解析器 DataReader
负责将Proxy获取的数据解析出来传换成Record并存入Store中。相当于C#的DataReader。
数据集 Store
一个保存数据的集合,类似于C#的Datatable。
Extjs3的Proxy较以前版本有了一些变动,资料很少,而且官方文档上相当简练,以至于一个完整的例子都没有…… 我尽力理解……

1. 数据记录
一条数据记录一般是有多个字段组成的。字段由Ext.data.Field类定义。Field的配置项很丰富,使我们有足够的信息在弱类型的语言中处理我们的数据,主要有:

name:字段名;defaultValue:默认值;type:数据类型,可以是string,int,float,boolean,date和auto(默认)。先介绍这么多,其余的在具体用到的时候再介绍。

要建立一个数据记录类(注意不是具体一条数据),可以使用Ext.data.Record.create方法,这个方法接受一个数组的Field类的配置项,返回一个构造函数。看一个例子:

<script type="text/javascript"> 
// create a Record constructor from a description of the fields 
var TopicRecord = Ext.data.Record.create([ // creates a subclass of Ext.data.Record 
{name: 'title' }, 
{ name: 'author', allowBlank: false }, 
{ name: 'totalPosts', type: 'int' }, 
{ name: 'lastPost',type: 'date' }, 
// In the simplest case, if no properties other than name are required, 
// a field definition may consist of just a String for the field name. 
'signature' 
]); // create Record instance 
var myNewRecord = new TopicRecord( 
{ 
title: 'Do my job please', 
author: 'noobie', 
totalPosts: 1, 
lastPost: new Date(), 
signature: '' 
}, 
id // optionally specify the id of the record otherwise one is auto-assigned 
); 
alert(myNewRecord.get('author')); 
</script>

这里演示的仅仅是Record最基本的功能:定义字段和存取数据。Record还可以和Store一起,由Store跟踪Record的变化情况。就如C#的DataTable一样,可以跟踪其内部的DataRow变更的情况。Extjs几乎把前台开发变成了后台。这些内容等介绍Store的时候再介绍。

2.数据代理
Ext.data.DataProxy是数据代理的抽象基类,实现了DataProxy的通用公共接口。DataProxy的最重要的通用方法就是doRequest,执行这个方法之后将从各种具体的数据源读取数据。继承自DataProxy的具体Proxy类有:

2.1 HttpProxy

这是最常用的proxy,通过一个http请求从远程服务器获取数据。HttpProxy最重要的配置项就是配置获取数据的url。HttpProxy不仅仅支持获取数据,它支持对数据的CRUD操作。DataProxy的api属性就是用来配置这4种操作对应的url的。如果不配置,就采用HttpProxy的url属性。例如:

api: { 
read: '/controller/load', 
create : '/controller/new', // Server MUST return idProperty of new record save : '/controller/update', 
destroy : '/controller/destroy_action' 
}

注意,extjs的官方文档这里相当含糊不清:
Extjs学习笔记之九 数据模型(上)
四个操作中的第一个到底是read还是load???
配置好api后,就可以执行doRequest方法,doRequest方法的参数比较复杂:

doRequest( String action, Ext.data.Record/Ext.data.Record[] rs, Object params, Ext.data.DataReader reader, Function callback, Object scope, Object arg )含义如下:action:表示执行的是哪种操作,可以是 create,read,update,destroy的一种。rs: 看了半天也没发现这个参数有什么用…… 看源代码发现其中出现了这样的表达式 url+rs.id,这个或许是为MVC架构的程序更好的构建url用的?直接忽略它,设为null即可。params:这个对象里边的属性:值对会作为post/get的参数传到服务器,非常有用。

reader: DataReader,将服务器返回的数据解析成Record的数组。下面会有更详细的解释。

callback:当读取到服务器数据之后执行的函数。这个函数接受三个参数,分别是: r Ext.Record[],服务器端返回的经过reader的数组。这是官方的说法,实际测试下来似乎只有当action是read的时候才是这样,下面有介绍;options:就是arg参数的值。success:是否成功的标致,bool,这个也是服务器端返回的。

scope:作用域

arg:一些附加的参数,会被传到callback的options参数中。

下面我们来完成一个例子,利用httpproxy完成基本的CRUD操作。先看服务器端代码:

<%@ WebHandler Language="C#" Class="dataproxy" %> using System; 
using System.Web; 
using System.Collections.Generic; 
public class dataproxy : IHttpHandler { 
static List<Student> db = new List<Student>(); 
static dataproxy() 
{ 
db.Add(new Student { Id = "1", Name = "Li", Telephone = "1232" }); 
db.Add(new Student { Id = "2", Name = "Wang", Telephone = "5568" }); 
db.Add(new Student { Id = "3", Name = "Chen", Telephone = "23516" }); 
db.Add(new Student { Id = "4", Name = "Zhu", Telephone = "45134" }); 
db.Add(new Student { Id = "5", Name = "Zhou", Telephone = "3455" }); 
} 
public void ProcessRequest (HttpContext context) { 
string id = context.Request.Params["id"]; 
string action=context.Request.Params["action"]; 
string result = "{success:false}"; 
if (action == "create") 
{ 
} 
else if (action == "read") 
{ 
foreach (Student stu in db) 
{ 
if (stu.Id == id) 
{ 
result = "{success:true,r:[['" + stu.Id + "','" + stu.Name + "','" + stu.Telephone + "']]}"; 
break; 
} 
} 
} 
else if (action == "update") 
{ 
} 
else if (action == "delete") 
{ 
} 
context.Response.ContentType = "text/plain"; 
context.Response.Write(result); 
} 
public bool IsReusable { 
get { 
return false; 
} 
} 
class Student 
{ 
string id; 
public string Id 
{ 
get { return id; } 
set { id = value; } 
} 
string name; 
public string Name 
{ 
get { return name; } 
set { name = value; } 
} 
string telephone; 
public string Telephone 
{ 
get { return telephone; } 
set { telephone = value; } 
} 
} 
}

我们用一个静态的List来模仿数据库。在处理函数中分别应对4种情况。上面仅实现了read的代码,返回一个数组,因为我们最终客户端采用ArrayReader来解析数据。服务器端的代码没什么好解释的,很简单,再看客户端的:
<head> 
<title>Data Proxy</title> 
<link rel="Stylesheet" type="text/css" href="ext-3.1.0/resources/css/ext-all.css" /> 
<script type="text/javascript" src="ext-3.1.0/adapter/ext/ext-base-debug.js"></script> 
<script type="text/javascript" src="ext-3.1.0/ext-all-debug.js"></script> 
<script type="text/javascript" src="ext-3.1.0/src/locale/ext-lang-zh_CN.js"></script> 
<script type="text/javascript"> 
var Student = Ext.data.Record.create(['id', 'Name', 'Telephone']); 
var arrayReader = new Ext.data.ArrayReader({ 
root: 'r', idIndex: 0, fields: Student }); 
var httpProxy = new Ext.data.HttpProxy({ 
url: 'dataproxy.ashx', 
api: { 
read: 'dataproxy.ashx?action=read', 
create: 'dataproxy.ashx?action=create', 
update: 'dataproxy.ashx?action=update', 
destroy: 'dataproxy.ashx?action=delete' 
} 
}); 
Ext.onReady(function() { 
var form = new Ext.FormPanel({ 
renderTo: document.body, 
height: 160, 
width: 400, 
frame: true, 
labelSeparator: ':', 
labelWidth: 60, 
labelAlign: 'right', 
defaultType: 'textfield', 
items: [ 
{ fieldLabel: 'ID', 
id: 'ID' 
}, 
{ fieldLabel: 'Name', 
id: 'Name' 
}, 
{ fieldLabel: 'Telephone', 
id: 'Telephone' 
} 
], 
buttons: [{ text: 'Read', handler: function() { 
httpProxy.doRequest('read', null, { id: form.getForm().findField('ID').getValue() }, arrayReader, 
function(r, option, success) { 
if (option.arrayData.success) { 
var res = r.records[0]; 
Ext.Msg.alert('Result From Server', res.get('id') + ' ' + res.get('Name') 
+' '+ res.get('Telephone')); 
} 
else { 
Ext.Msg.alert('Result','Did not find.'); 
} },this,arrayReader); 
} 
}, 
{ text: 'Delete' }, { text: 'Update' }, { text: 'Create'}] 
}) 
}); 
</script> 
</head>

这里有些东西要解释下,首先是定义了一个Student的Record,这个和服务器端的代码是一致的。然后定义了ArrayReader,ArrayReader是读取数组内的数据,数据格式参考服务器端的代码,它有一个root属性非常重要,指定的是读取json数据中哪个属性的值(这个值是一个数组的字面量).idIndex也是必须指定的,它标志着哪个字段是主键。fields就好理解了,读取的Record的字段。数组里边的顺序要和Record的字段顺序对应,否则可以通过Record的mapping属性来指定,例如: {name:'Telephone',mapping:4}就表示读取数组中第4个数值放到Telephone字段中。 下面就是定义httpProxy,设置好api。然后我们创建一个表单:

Extjs学习笔记之九 数据模型(上)

添加4个按钮。先为Read按钮写上处理函数:doRequest的一个参数是'read',第二个参数是null,因为我不懂它有什么用;第三个参数把要查询的ID的值传给服务器,第四个参数是一个reader,第五个参数callback很重要,我们在这里处理服务器的返回值。注意,我在最后一个参数设置为arrayReader,于是这个函数的option参数的值实际上就是arrayReader。我为什么要这样做呢,一来是做个演示,最后一个参数有什么用,二来是因为ArrayReader比较古怪,注意它没有公开的successProperty配置项,也就是说它无法判断服务器返回的success属性,也就是这个callback的success参数永远是undefined!我一开始以为是我服务器端的代码不对,后来debug进源代码,发现它确实不处理这个success属性。或许ArrayReader设计的本意就不是用在这个环境里的。不过作为演示,那就这样用吧。其实它不处理success参数我们自己还是可以处理的。arrayReader内部有个arrayData属性,它是一个解析好的json对象,如果返回的json字符串中有success属性那么这个对象也有success属性,这样我们就可以获得服务器的返回值,同理,也可以处理服务器返回的任何数据。当然,这种用法是文档上没有的,仅供演示。这个callback的第一个参数,要特别注意,文档上说是Record[],不过实际上它是一个对象,它的record属性才是Record[]。我只能说extjs这部分的文档很糟糕。幸好这部分的代码是很不错的,有兴趣的朋友可以调试进去看看,以便有更深刻的理解。好了,万事俱备,点击下Read按钮,结果出来了:

Extjs学习笔记之九 数据模型(上)

此文暂告一段落,其他几个操作原理上类似的,突然发现,如果单纯的用这个例子来演示似乎不太合适。因为Delete和Update服务器端都不需要返回什么数据,而doRequest强制要求用一个DataReader来解析返回的数据,很不方便。或许在操作表格型的数据的时候doRequest的其他方法才有用武之地。针对单个对象的CRUD,可以直接采用更底层的Ext.ajax方法(另文介绍),或者利用表单的方法来处理。

本文只是对Extjs的数据模型的功能和原理做一简单的介绍,在实际中如何高效的组织代码和在服务器与客户端间传递数据是一个另外的话题。Extjs还是很灵活的,客户端和服务器端的通信契约还是可以让程序员自己决定。

太长了…转下篇…

Javascript 相关文章推荐
HTML中事件触发列表与解说
Jul 09 Javascript
原生javascript获取元素样式属性值的方法
Dec 25 Javascript
jquery的attr方法禁用表单元素禁用输入内容
Jun 23 Javascript
node.js中的buffer.toJSON方法使用说明
Dec 14 Javascript
jquery带动画效果幻灯片特效代码
Aug 27 Javascript
JavaScript模块规范之AMD规范和CMD规范
Oct 27 Javascript
Javascript数组Array基础介绍
Mar 13 Javascript
weUI应用之JS常用信息提示弹层的封装
Nov 21 Javascript
layui表格实现代码
May 20 Javascript
表格展示利器 Bootstrap Table实例代码
Sep 06 Javascript
Vue中对iframe实现keep alive无刷新的方法
Jul 23 Javascript
如何使用Jquery动态生成二级选项列表
Feb 06 jQuery
JavaScript 事件冒泡简介及应用
Jan 11 #Javascript
Javascript 读书笔记索引贴
Jan 11 #Javascript
Javascript学习笔记9 prototype封装继承
Jan 11 #Javascript
Javascript学习笔记8 用JSON做原型
Jan 11 #Javascript
Javascript学习笔记7 原型链的原理
Jan 11 #Javascript
Javascript学习笔记6 prototype的提出
Jan 11 #Javascript
Javascript学习笔记5 类和对象
Jan 11 #Javascript
You might like
PHP图像识别技术原理与实现
2016/10/27 PHP
php中bind_param()函数用法分析
2017/03/28 PHP
两个SUBMIT按钮,如何区分处理
2006/08/22 Javascript
Mootools 1.2教程 选项卡效果(Tabs)
2009/09/15 Javascript
JS延时器提示框的应用实例代码解析
2016/04/27 Javascript
使用Web Uploader实现多文件上传
2016/06/08 Javascript
微信小程序 支付功能开发错误总结
2017/02/21 Javascript
js, jQuery实现全选、反选功能
2017/03/08 Javascript
微信小程序自定义prompt组件步骤详解
2018/06/12 Javascript
如何利用ES6进行Promise封装总结
2019/02/11 Javascript
使用Vue实现移动端左滑删除效果附源码
2019/05/16 Javascript
微信小程序实现录音时的麦克风动画效果实例
2019/05/18 Javascript
Jquery异步上传文件代码实例
2019/11/13 jQuery
node.js使用net模块创建服务器和客户端示例【基于TCP协议】
2020/02/14 Javascript
JavaScript交换变量常用4种方法解析
2020/09/02 Javascript
javascript实现放大镜功能
2020/12/09 Javascript
Mac下Supervisor进程监控管理工具的安装与配置
2014/12/16 Python
利用PyInstaller将python程序.py转为.exe的方法详解
2017/05/03 Python
Python 获取div标签中的文字实例
2018/12/20 Python
python使用opencv实现马赛克效果示例
2019/09/28 Python
python常见字符串处理函数与用法汇总
2019/10/30 Python
Python OpenCV实现测量图片物体宽度
2020/05/27 Python
python爬虫判断招聘信息是否存在的实例代码
2020/11/20 Python
Django模板报TemplateDoesNotExist异常(亲测可行)
2020/12/18 Python
Skyscanner阿联酋:全球领先的旅游搜索平台
2017/11/25 全球购物
哥德堡通行证:Gothenburg Pass
2019/12/09 全球购物
建筑专业自荐信
2013/10/18 职场文书
大学生入党思想汇报
2014/01/14 职场文书
个人近期表现材料
2014/02/11 职场文书
电子专业自荐信
2014/07/01 职场文书
四风查摆问题自查报告
2014/10/10 职场文书
2014年应急工作总结
2014/12/11 职场文书
2017春节晚会开幕词
2016/03/03 职场文书
导游词之无锡东林书院
2019/12/11 职场文书
vue引入Excel表格插件的方法
2021/04/28 Vue.js
Redis基本数据类型List常用操作命令
2022/06/01 Redis