Ext基础

本章简介

Ext JS是用于开发 RIA (富客户端)的Ajax应用,是使用JavaScript编写的、与后台技术无关的前端Ajax框架,主要用于创建前端用户界面。因此,可以将 Ext JS用于.NETJavaPHP等各种语言开发的应用中。最初,Ext JS基于YUI技术,从UI界面中 CSS样式的应用到数据解析中的异常处理,它都是一款不可多得的 JavaScript客户端技术精品。

本章将讲解Ext JS的发展及其特点,了解Ext JS的含义、熟悉 Ext JS开发环境,并在此基础上实现Ext绚丽效果。然后,详细讲解 Ext表格。在整个Ext 中,表格控件在界面和功能上都是最重要的,包括排序、缓存、拖动、隐藏列、显示行号以及编辑单元格等功能。通过Ext表格可以实现选择一条或多条记录、高亮显示选择行、显示行号、支持复选框以及支持本地和远程分页等特性。

核心技能部分

1.1Ext简介

1.1.1Ext发展史

Ext最早是在YUI库的基础上扩展开来的,因此Ext早期被称为 Yui-Ext。2005 年,Jack Slocum(杰克·洛克姆)选择YUI库作为底层库来维护一个Ajax项目,此后的一段时间他都围绕 YUI进行开发。但随着YUI越来越大、功能需求越来越多,他逐渐发现维护 YUI并不容易。在工作中,Jack Slocum又接触了 Swing—Java平台上的 UI库,并使用了极少的时间研究、改写YUI,使之呈现较先进的 Swing UI理念。这样,Jack Slocum在写技术博客的同时以 Yui-Ext的形式开放自己编写的 UI,包括 Grid、Tree等UI组件。在 Jack 的开发和社区氛围的营造下,Yui-Ext 已经成为一个成熟的 Ajax UI框架,且此框架是独立的,不受 YUI 的影响并兼容 JQuery、Prototype 等多种JS库。此时,Yui-Ext改名为 ExtJS。

2006年初,Jack Slocum为将一套公用设施扩建为 Yahoo!User Interface(YUI)库而工作。这些扩展很快组织成一个独立的库代码并以“Yui-Ext”的名义发布。2006 年秋,Jack发行Yui-Ext 0.33 版本,此版本被证明为最终版本。在2006年年底之前,该库已大受欢迎,其名称被简化为Ext,反映了该技术作为框架的成熟性和独立性。

2007 年 4月1日,Ext发布了 1.0 正式版;2007 年 2 月,Ext 获得某个新成立的公司的财务支持,增加了许多强大的功能。Ext 2.0 已经具备了很多 Swing 的特性,components、containers、layouts等概念都应用在内。Ext 2.0是一个真正成熟的框架,各方面的完善程度较高,升级到 Ext3.0 时,底层结构和配置代码均无须较大改动。Ext 3.0增加了 Ext Direct、DataWriters等强功能。

2008 年 4 月 1 日,Ext JS 已经涵盖了美国、日本、法国、德国、中国等全球范围的用户,版本为 Ext-3.O。

官方在2009 年 4月l4-16日的首次Ext 发布会中,发布了 Ext 3.0 RC版本。

1.1.2Ext简介

Ext JS可以用于开发RIA (富客户端)的 Ajax应用,是使用 JavaScript编写的、与后台技术无关的前端Ajax框架,主要用于创建前端用户界面。因此,可以将 Ext JS用于.NET、Java、PHP 等各种语言开发的应用中。最初,Ext JS 基于 YUI技术,由 Jack Slocum开发。该框架参考 Java Swing等机制组织可视化组件,从UI界面中 CSS样式的应用到数据解析中的异常处理,它都是一款不可多得的 JavaScript客户端技术精品。Ext的 UI组件模型和开发理念脱胎成形于Yahoo组件库YUI和 Java平台上 Swing,并为开发者屏蔽了大量跨浏览器的处理。相对而言,Ext 比直接针对DOM、W3C对象模型开发 UI组件更为轻松。

Ext JS初期仅是对Yahoo!UI的对话框扩展,后来逐渐形成自己的特色,深受网友的喜爱。如今,除了 YUI外,Ext还支持JQuery、Prototype 等多种JS底层库,以供用户自由选择。该框架完全基于纯HTML/CSS+JS 技术,提供丰富的跨浏览器UI组件,可以灵活地采用 JSON数据源开发,真正减轻服务端表示层的负荷,从而实现客户端的 MVC应用。Ext JS支持多平台下的主流浏览器 Internet Explorer 6+、Firefox 1.5+、Safari 2+、Opera 9+。使用该技术的厂家包括IBM、Adobe、Cisco等。

JQuery、Prototype 和 YUI都属于核心的 JS 库。虽然 YUI、JQuery 各自构建了一系列 UI 器件(Widget),但没有一个真正整合良好、完整的程序开发平台。在实际开发环境中,开发者需要通过大量的工作来完善开发环境。使用 Ext可以填补这些缺陷。目前,主流开源框架中只有 DOJO与Ext在尝试提供整合的开发平台。与DOJO工具包相比,Ext可以提供粘合度更高的应用程序框架,其各个组件在设计之时就要求与其他Ext组件一起工作,进行无缝对接。这种流畅的互通性需要团队的紧密合作,并时刻强调设计和开发目标的统一。从构建每个Ext组件开始,始终都强调组件的外观、性能、互通性和可扩展性。

Ext完全可以单独使用。实际上,除了特定要求外,推荐单独使用 Ext,使文件占位更小、支持和整合更加紧密。同样,Ext 支持与 JQuery、YUI 或 Prototype整合使用,作为底层库的角色出现,提供处理各种核心的服务,如 DOM和事件处理、Ajax连接和动画特效。使用整合方式的原因之一是它们已具备了一些特定的组件,而Ext并没有原生支持。例如,YUI 的 History控件便是一个典型的应用。此时,Ext需要依赖YUI库的底层实现History控件,从而免去 Ext 自身底层库,减少整个程序的内存占用。另外,使用整合方式时,许多已在使用其他底层库的程序可以逐步加入 Ext。总之,如果程序中已经存在其他库,则 Ext可以通过利用它们为用户提供各种可能性和性能上的优化。只要实现了对应的底层库接口,可以为任意一个框架添加适配器。用户可以轻松地将 DOJO、Moo、Ajax.NET或其他JS库转变为 Ext的底层。

1.1.3Ext类库

使用 ExtJS需要首先获得Ext JS库文件,该框架是开源的,可以直接从官方网站 http://www.sencha.com/下载


下载后的 ext-3.0.0.zip文件后解压

2-1-1 Ext 3 的目录

名称

说明

adapter

负责将提供的第三方底层库 (包括 Ext 白带的底层库)映射为 Ext 支持的底层库

docs

API 帮助文档

exmaples

提供使用 Ext JS技术实现的实例

pkgs

新的工具包

resources

Ext UI资源文件目录,CSS、图片文件等都存放在此目录

src

无压缩 Ext 全部的源码

ext-all.js

压缩后的 Ext 全部源码

ext-all-debug.js

无压缩的 Ext 全部的源码 (用于调试)

Ext JS由一系列类库组成,一旦页面成功加载了 Ext JS库,就可以在页面中通过JavaScript调用Ext JS的类及控件实现需要的功能。

1)底层 API (core):底层API 中提供了对DOM操作、查询的封装、事件处理、DOM查询器等基础功能,如图 2.1.3 所示。

2.1.3 Ext底层 API

2)控件 (widgets):可以直接在页面中创建的可视化组件,如面板、选项板、表格、树、窗口、菜单、工具栏、按钮等。在应用程序中,可以直接通过应用这些控件实现友好、交互性强的应用程序的 UI


3)实用工具(util):Ext提供了许多的实用工具,可以方便地实现数据内容格式化、JSON数据解码反解码、对 Date 和 Array 发送 Ajax请求、Cookie 管理、CSS 管理等扩展功能


Ext应用需要在页面中引人Ext 的样式及 Ext库文件,样式文件为 resources/css/ext-all.css,Ext 的JS库文件主要包含 adapter/ext/ext-base.js 和 ext-all.js。其中,ext-base.js 表示框架基础库,ext-all.js是 Ext JS 的核心库。因此,使用 Ext JS框架的页面中一般包含以下代码:

<link rel="stylesheet" type="text/css" href="${ext目录}/resources/css/ext-all.css"/>

<script type="text/javascript" src="${ext目录}/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="${ext目录}/ext-all.js"></script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>helloworld</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(

function(){

var win = new Ext.Window( {title:'hello',width:200,height:200,html:'<h1>hello my first Ext</h1>'} );

win.show();

}

);

</script>

</head>

<body>

</body>

</html>

示例 2.1 是一个简单的Ext示例,运行结果如图 2.1.6所示。

2.1.6 Ext 的 hello 示例

由示例 2.1 中的 JS 代码可知,Ext JS 一般的程序入口为“Ext.onReady();”,然后可以创建 window对象。该对象中有很多属性,具体可以查看下载包中 doc文件夹下的 API。

Ext的样式及Ext库文件需要找到相应的文件,所以可以直接在Ext解压包examples下创建实例,或者从解压的目录中提取需要的文件到使用者的工程中。

1.1.4Ext组件

Ext具有结构、层次分明的组件体系,这些组件形成了 Ext 的控件。Ext组件由 Component类定义,每种组件都有一个指定的 xtype 属性值,通过该值可以得到组件的类型或定义指定类型的组件。

一般而言,组件可以分为 3 类,即基本组件、工具栏组件、表单及元素组件,分别见表 2-1-2、表 2-1-3、表 2-1-4。

9-1-2 基本组件

xtype

Class

解 释

box

Ext.BoxComponent

具有边框属性的组件

button

Ext.Button

按钮

color palette

Ext.ColorPalette

调色板

component

Ext.Component

组件

container

Ext.Container

容器

cycle

Ext.CycleButton

切换按钮

dataview

Ext.DataView

数据显示视图

datepicker

Ext.DatePicker

日期选择面板

editor

Ext.Editor

编辑器

editorgrid

Ext.grid.EditorGridPanel

可编辑的表格

grid

Ext.grid.GridPanel

表格

paging

Ext.PagingToolbar

工具栏中的间隔

progress

Ext.ProgressBar

进度条

splitbutton

Ext.SplitButton

可分裂的按钮

tabpanel

Ext.TabPanel

选项面板

treepanel

Ext.tree.TreePanel

viewport

Ext.ViewPort

视图

window

Ext.Window

窗口

9-1-3 工具栏组件

xtype

Class

解 释

toolbar

Ext.Toolbar

工具栏

tbbutton

Ext.Toolbar.Button

按钮

tbfill

Ext.Toolbar.Fill

文件

tbitern

Ext.Toolbar.Item

工具条项目

tbseparator

Ext.Toolbar.Separator

工具栏分隔符

tbspacer

Ext.Toolbar.Spacer

工具栏空白

tbsplit

Ext.Toolbar.SplitButton

工具栏分隔按钮

tbtext

Ext.Toolbar.TextItem

工具栏文本项

9-1-4 表单及元素组件

xtype

Class

解 释

form

Ext.FormPanel

Form面板

checkbox

Ext.form.Checkbox

checkbox 录入框

combo

Ext.form.ComboBox

Combo选择项

datefield

Ext.form.DateField

日期选择项

field

Ext.form.Field

表单字段

fieldset

Ext.form.FieldSet

表单字段组

hidden

Ext.form.Hidden

表单隐藏域

htmleditor

Ext.form.HtmlEditor

html 编辑器

numberfield

Ext.form.NumberField

数字编辑器

radio

Ext.form.Radio

单选按钮

textarea

Ext.form.Text Area

区域文本框

textfield

Ext.form.TextField

表单文本框

timefield

Ext.form.TimeField

时间录入项

trigger

Ext.form.TriggerField

触发录入项

组件可以直接通过new关键字创建。例如,示例 2.1 使用 new Ext.Window 创建窗口,使用 new Ext.GridPanel()创建表格。除了一些普通的组件外,一般都会在构造函数中通过传递构造参数创建组件。组件的构造函数中一般都可以包含一个对象,该对象包含创建组件需要的配置属性及值,组件根据构造函数中的参数属性值进行初始化。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(

function(){

var panel = new Ext.Panel({ title:"hello",width:300,height: 150,html: "<h1>Hello</h1>" } );

panel.render("hello");

}

);

</script>

</head>

<body>

<div id="hello"></div>

</body>

</html>

示例 2.2 中使用了 Panel面板,运行结果如图2.1.7所示。

2.1.7 Ext 的 Panel 的构造函数

1.1.5Ext事件

ExtJS提供了一套强大的事件处理机制,用于响应用户的动作、监控控件状态变化、更新控件视图信息、与服务器进行交互等。事件统一由 Ext.EventManager对象管理,与浏览器W3C 标准事件对象 Event对应。Ext封装了一个 Ext.EventObject事件对象。支持事件处理的类或接口为 Ext.util.Observable,凡是继承该类的组件或类都支持向对象中添加事件处理及响应功能。

某按钮的点击事件代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(function(){

Ext.get('myButton').on('click',function(){

alert('你点击到我了');

});

});

</script>

</head>

<body>

<input type="button" id="myButton" value="myButton"/>

</body>

</html>

1.2Ext表格控件 Grid

1.2.1Grid特性

Ext的表格功能非常强大,包括排序、缓存、拖动、隐藏列、显示行号以及编辑单元格等。表格由类 Ext.grid.GridPanel定义,它继承自 Panel。在 Ext 中,Grid控件和其他显示数据的控件能够支持多种数据类型 (二维数组、JSON数据和 XML数据等)甚至自定义的数据类型。Ext提供了一个桥梁 Ext.data.Store,通过它可以将任何格式的数据转化成 Grid能够使用的形式,不需要为每种数据格式编写一个 Grid 的实现。另外,表格控件Grid还必须包括列定义信息,表格的列信息由类Ext.grid.ColumnModel定义,而表格的数据存储器由 Ext.data.Store定义,数据存储器根据解析的数据不同分为 JsonStore、SimpleStore、GroupingStore等。

Ext Grid的功能包括选择一条或多条记录、高亮显示选择行、调整列宽、显示行号、支持复选框以及支持本地和远程分页。另外,Grid可以编辑表格、添加行、删除一行或多行、拖动改变表格大小,这些功能都在Ext表格控件中实现。

1.2.2简单的 Grid

查看 Ext解压包的 examples 目录中的示例制作 Grid,加深对 Grid 的了解。

(1)表格是二维表格,与设计数据库的表相同,需要首先设置表的列数、列名、列的类型及显示方式,搭建表格框架。Grid的结构和数据库中的表非常相似。

2)在Ext 中,列的定义称为 ColumnModel,简称 cm。作为整个表格的列模型,列必须首先建立。创建一个 6列的 Grid,按顺序分别为编号(empId)、姓名(userName)、性别 (sex)、出生日期(birthday)、地址(address)和备注(remark),代码如下:

var cm = new Ext.grid.ColumnModel( [

{header:'编号',dataIndex:'empId'},

{header:'姓名',dataIndex:'empName'},

{header:'性别',dataIndex:'sex'},

{header:'出生日期',dataIndex:'birthday'},

{header:'地址',dataIndex:'address'},

{header:'备注',dataIndex:'remark'}

]);

上述代码中,var cm = new Ext.grid.ColumnModel()用于创建表格列信息。表格包含的列由 columns配置,每列的header表示该列的名称,dataIndex表示列对应的记录集字段。另外,sortable表示是否可以排序,renderer表示列的渲染函数,width表示宽度,format表示格式化信息等。

定义表格的结构后,就可以向其中添加数据。此处,数据也是二维的。直接添加静态数据的代码如下:

var data = [

['0001','张三','boy','9/1 12:00am','建设路','0001remark'],

['0002','李四','人民路','0002remark'],

['0003','王五','大学路','0003remark'],

['0004','赵六','girl','南京路','0004remark']

];

上述代码中,“var data =…”用于定义表格中的数据,共包含4条记录,是一个二维数组,在页面上显示为4行,每行6列,分别对应 empId、userName、sex、birthday、address 和 remark。另外,在页面上显示这些数据时需要对原始数据进行转换,代码如下:

var store = new Ext.data.Store({

proxy:new Ext.data.MemoryProxy(data),

reader:new Ext.data.ArrayReader({},[

{name:'empId'},

{name:'empName'},

{name:'sex'},

{name:'birthday'},

{name:'address'},

{name:'remark'}

])

});

上述代码中,“var store = new Ext.data.Store()” 用于创建数据的存储对象,负责将各种原始数据(如二维数组、JSON对象数组、文本等) 转换成Grid可以使用的形式,避免为每种数据格式都编写对应的实现。此外,store包含 proxy和reader两个部分,前者指获取数据的方式,后者指解析数据的方式。

Ext.data.MemoryProxy用于解析JavaScript变量,只要将已定义的 data作为参数传入即可。Ext.data.ArrayReader用于解析数组,说明数组将按照定义的规范进行解析。

上述代码定义了名称 empId、userName、sex、birthday、address 和 remark,与表格 cm 的 dataIndex一一对应。

为了使数据可以显示,需要通过“store.load();”对数据进行初始化。

定义列模型并完成原始数据和数据转换后,可以进行装配。创建Grid,代码如下:

var grid = new Ext.grid.GridPanel({

store:store,

height:350,

width:700,

cm:cm

});

创建了 Grid之后,需要使用 grid.render()方法使Grid开始渲染,才能显示数据。完整的 Grid实例代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>表格</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

</head>

<body>

<div id="gridCm" style="height:300px;"></div>

<script type="text/javascript">

var cm = new Ext.grid.ColumnModel( [

{header:'编号',dataIndex:'remark'}

]);

var data = [

['0001','0004remark']

];

var store = new Ext.data.Store({

proxy:new Ext.data.MemoryProxy(data),

{name:'remark'}

])

});

var grid = new Ext.grid.GridPanel({

store:store,

cm:cm

});

store.load();

grid.render('gridCm');

</script>

</body>

</html>


1.2.3Grid 常用功能

2.2.2小节中演示了如何创建简单的 Grid表格,本节将对该Grid进行完善。

1. 互换列位置

互换姓名和性别的位置,最直接的方法是互换两列的所有信息,但此操作比较繁琐。使用 Ext.data.AnayReader解析数组时,可以使用 mapping指定列的位置,代码变化如下:

var store = new Ext.data.Store({

proxy:new Ext.data.MemoryProxy(data),[

{name:'empId',mapping:0},

{name:'empName',mapping:2},

{name:'sex',mapping:1},

{name:'birthday',mapping:3},

{name:'address',mapping:4},

{name:'remark',mapping:5}

])

});


mapping的索引号从0开始。

2. 自定义列宽

2.2.2 小节的 Grid 中,所有的列宽都相同。当列不够宽时,用户必须手动调整其宽度。cm支持设置列宽,不设置时会取默认的列宽 lOOpx。

var cm = new Ext.grid.ColumnModel( [

{header:'编号',dataIndex:'empId',width:40},//指定列宽

{header:'姓名',dataIndex:'empName',width:60},dataIndex:'sex',dataIndex:'birthday',width:120},dataIndex:'address',width:200},dataIndex:'remark',width:200}

]);

上述代码对列宽进行了适当调整,运行效果如图 2.1.11 所示。


使用这种方式必须在每次应用时都计算列宽,依然比较繁琐。程序需要使每列自动填满 Grid,以减少工作量。通过viewConfig的 forceFit进行配置,可以重新计算所有列宽后填充Grid表格,代码如下:

viewConfig:{forceFit:true} //自适应列宽



3. 支持按列排序

JSP 中,实现排序比较复杂;而在Ext中,只要添加 sortable的属性,就可以方便地进行排序。

var cm = new Ext.grid.ColumnModel( [

{header:'编号',sortable:true},//指定列宽,排序

{header:'姓名',sortable:true}

]);


当为列标题添加的 sortable 属性为 true 时,标题上会出现一个向上或向下的小箭头,分别表示按标题的升序或者降序排列。

标题的右侧有一个可下拉的、类似于Extl.x 的右键功能菜单

除了可以按照升序或降序排序外,此功能菜单还可以隐藏或显示列。

4. 格式化数据

表格中的“出生日期”的值没有经过格式化,所以并不直观。在实际显示时,需要对特定列的数据进行格式化,步骤如下:

1)确定“出生日期”属于日期格式的数据。

2)在 reader 中增加配置,除了设置name属性外,还需要设置type 和 dateFormat属性。其中,type说明解析时将该列作为何种类型处理,dateFormat说明将字符串转换成相应的日期格式。在Ext 中,日期格式有相应的约定:Y表示年、m表示月、d表示日期、H表示小时、i表示分钟、S表示秒。改动后的代码如下:

var cm = new Ext.grid.ColumnModel( [

{header:'编号',renderer:Ext.util.Format.dateRenderer('Y-m-d H:i:s')},sortable:true}

]);

运行上述代码,查看运行结果,如图 2.1.17所示。

2.1.17 日期格式化

5. 自动显示行号

Ext 中,自动显示行号非常简单,只要在cm中添加RowNumberer对象即可。

var cm = new Ext.grid.ColumnModel( [

new Ext.grid.RowNumberer(),//自动显示行号

{header:'编号',sortable:true,

renderer:Ext.util.Format.dateRenderer('Y-m-d H:i:s')},//格式化

{header:'地址',sortable:true}

]);


6. 复选框

Ext的复选框通过CheckboxSelectionModel对象实现,它在每行数据前添加一个复选框。

1)创建sm,代码如下

var sm = new Ext.grid.CheckboxSelectionModel();

2)将 sm放入cm和 grid中,代码如下:

var cm = new Ext.grid.ColumnModel( [

new Ext.grid.RowNumberer(),//自动显示行号

sm,//添加复选框

{header:'编号',sortable:true}

]);



7. 改变字体颜色、添加图片

在定义列的时候可以指定该列的渲染函数,在函数里可以设置字体颜色、添加图片。

var cm = new Ext.grid.ColumnModel( [

{header:'编号',width:40,renderer:renderSex},width:200}

]);

function renderSex(value)

{

if(value == 'male')

return "<span style='color:red;font-weight:bold;'>红男</span><img src='m.gif'/>";

else

return "<span style='color:green;font-weight:bold;'>绿女</span><img src='m.gif'/>";

}

本章总结

ØExt JS是用于开发 RIA (富客户端)的Ajax应用,是使用JavaScript编写的、与后台技术无关的前端Ajax框架,主要用于创建前端用户界面。

ØExt应用需要在页面中引人Ext 的样式及 Ext库文件。

n样式文件为 resources/css/ext-all.css

nExt JS库文件主要包含 adapter/ext/ext-base.js ext-all.js。其中,ext-base.js 表示框架基础库,ext-all.jsExt JS 的核心库。

ØExtJS组件可以分为 3 类,即基本组件、工具栏组件、表单及元素组件。

ØExt组件由 Component类定义,每种组件都有一个指定的 xtype 属性值,通过该值可以得到组件的类型或定义指定类型的组件。

Ø事件统一由 Ext.EventManager对象管理,与浏览器W3C 标准事件对象 Event对应。Ext封装了一个 Ext.EventObject事件对象。

ØExt的表格功能非常强大,包括排序、缓存、拖动、隐藏列、显示行号以及编辑单元格等。表格由类 Ext.grid.GridPanel定义,它继承自 Panel。

n Ext中,Grid控件和其他显示数据的控件能够支持多种数据类型 (二维数组、JSON数据和 XML数据等)甚至自定义的数据类型。而表格的数据存储器由 Ext.data.Store定义,数据存储器根据解析的数据不同分为 JsonStore、SimpleStore、GroupingStore等。

n另外,表格控件Grid还必须包括列定义信息,表格的列信息由类Ext.grid.ColumnModel定义。

任务实训部分

1Ext Grid 控件的显示功能

训练技能点

Ø使用 Ext Grid 控件显示后台 Servlet 查询的数据

需求说明

(1)使用 Servlet 查询数据。

(2)使用 Ext Grid 显示后台 Servlet 查询的数据。

实现步骤

(1)设计数据库表及字段。

(2)使用 Servlet 查询订单数据。

(3)使用 Ext Grid 控件显示查询数据。

参考代码

创建数据库表、添加数据的代码:

-- ----------------------------

-- Table structure for pro_order

-- ----------------------------

DROP TABLE IF EXISTS `pro_order`;

CREATE TABLE `pro_order` (

`order_id` int(11) NOT NULL AUTO_INCREMENT,

`order_no` varchar(20) DEFAULT NULL,

`price` float DEFAULT NULL,

`create_date` varchar(20) DEFAULT NULL,

PRIMARY KEY (`order_id`)

) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

-- ----------------------------

-- Records

-- ----------------------------

INSERT INTO `pro_order` VALUES ('1','0001','2000','2011-01-01');

INSERT INTO `pro_order` VALUES ('2','0002','200','2011-01-01');

INSERT INTO `pro_order` VALUES ('3','0003','3000','2011-01-01');

INSERT INTO `pro_order` VALUES ('4','0004','50','2011-01-01');

INSERT INTO `pro_order` VALUES ('5','0005','30','2011-01-01');

INSERT INTO `pro_order` VALUES ('6','0006','2011-01-01');

INSERT INTO `pro_order` VALUES ('7','0007','34','2011-01-01');

INSERT INTO `pro_order` VALUES ('8','0008','57','2011-01-01');

INSERT INTO `pro_order` VALUES ('9','0009','300','2011-01-05');

INSERT INTO `pro_order` VALUES ('10','0010','80','2011-01-05');

INSERT INTO `pro_order` VALUES ('11','0011','90','2011-01-05');

INSERT INTO `pro_order` VALUES ('12','0012','3090','2011-01-05');

数据库连接类:

public class DBUtil {

public static Connection getCon(){

Connection conn=null;

String url="jdbc:mysql:///test";

String userName="root";

String userPwd="admin";

try {

conn=DriverManager.getConnection(url,userName,userPwd);

} catch (Exception e) {

e.printStackTrace();

}

return conn;

}

public static void closeDB(Connection conn,Statement stmt,PreparedStatement pstmt,ResultSet rs){

try {

if (rs!=null) {

rs.close();

}

if (pstmt!=null) {

pstmt.close();

}

if (stmt!=null) {

stmt.close();

}

if (conn!=null) {

conn.close();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

查询订单的Servlet 方法:

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException,IOException {

response.setContentType("text/html;charset=gbk");

response.setCharacterEncoding("gbk");

request.setCharacterEncoding("gbk");

PrintWriter out = response.getWriter();

Connection conn=null;

Statement stmt=null;

PreparedStatement pstmt=null;

ResultSet rs=null;

String hqlSql="select count(*) from pro_order";

String sql="select * from pro_order";

String json="";

int totalOrder=0;

try {

conn=DBUtil.getCon();

stmt=conn.createStatement();

rs=stmt.executeQuery(hqlSql);

while (rs.next()) {

totalOrder=rs.getInt(1);

}

json="{totalProperty:"+totalOrder+",root:[";

rs=stmt.executeQuery(sql);

while (rs.next()) {

json+="{orderNo:'"+rs.getString("order_no")+"',price:'"+rs.getString("price")+

"',createDate:'"+rs.getString("create_date")+"'},";

}

} catch (Exception e) {

e.printStackTrace();

}finally{

DBUtil.closeDB(conn,stmt,pstmt,rs);

}

json=json.substring(0,json.length()-1);

json+="]}";

System.out.println(111);

out.write(json.toString());

}

查询构造的JSON格式数据:

root:[

{orderNo:'0001',price:'2000',createDate:'2011-01-01'},

{orderNo:'0002',price:'200',

{orderNo:'0003',price:'3000',

{orderNo:'0004',price:'50',

{orderNo:'0005',price:'30',

{orderNo:'0006',

{orderNo:'0007',price:'34',

{orderNo:'0008',price:'57',

{orderNo:'0009',price:'300',createDate:'2011-01-05'},

{orderNo:'0010',price:'80',

{orderNo:'0011',price:'90',

{orderNo:'0012',price:'3090',createDate:'2011-01-05'}

]

使用Ext 表格控件显示数据:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>proOrderList</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="this is my page">

<meta http-equiv="content-type" content="text/html; charset=gbk">

<!-- 第一步引入extjs的样式文件 -->

<link rel="stylesheet" type="text/css" href="ext-3.3.1/resources/css/ext-all.css">

<!-- 第二步引入extjs的库文件,底层驱动 -->

<script type="text/javascript" src="ext-3.3.1/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.3.1/ext-all.js"></script>

<script type="text/javascript" src="proOrderList.js"></script>

</head>

<body>

<div id="grid"></div>

<script type="text/javascript">

Ext.onReady(function() {

var cm = new Ext.grid.ColumnModel([

{header : "订单编号",dataIndex : 'orderNo'},

{header : "订单价格",dataIndex : 'price' },

{header : "创建日期",dataIndex : 'createDate'}]);

var store=new Ext.data.Store({

proxy:new Ext.data.HttpProxy({url:'Pro_orderServlet'}),

reader:new Ext.data.JsonReader({totalProperty:'totalProperty',root:'root'},

[{name:'orderNo'},{name:'price'},{name:'createDate'}])

});

var grid=new Ext.grid.EditorGridPanel({

renderTo:'grid',

store:store,

cm:cm,

loadMask:true,

width:600,

height:300

});

store.load({params:{start:0,limit:10}});

});

</script>

</body>

</html>

2Ext Grid 控件的分页功能

训练技能点

Ø使用 Ext Grid 控件分页功能

需求说明

在完成上一任务显示功能的基础上,使用Ext Grid 控件实现数据分页,效果如图9.2.2所示。

2.2.2 分页显示订单

实现步骤

(1)设计数据库表及字段。

(2)使用 Servlet 查询订单数据。

(3)使用 Ext Grid 控件分页显示查询数据。

参考代码

查询订单的Servlet 方法:

public void doGet(HttpServletRequest request,IOException {

response.setContentType("text/html;charset=gbk");

response.setCharacterEncoding("gbk");

request.setCharacterEncoding("gbk");

PrintWriter out = response.getWriter();

//分页

String start = request.getParameter("start");

String limit = request.getParameter("limit");

Connection conn=null;

Statement stmt=null;

PreparedStatement pstmt=null;

ResultSet rs=null;

String hqlSql="select count(*) from pro_order";

String sql="select * from pro_order limit "+start + "," + limit;

String json="";

int totalOrder=0;

try {

conn=DBUtil.getCon();

stmt=conn.createStatement();

rs=stmt.executeQuery(hqlSql);

while (rs.next()) {

totalOrder=rs.getInt(1);

}

json="{totalProperty:"+totalOrder+",json.length()-1);

json+="]}";

out.write(json.toString());

}

使用Ext Grid 控件分页显示:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>

<head>

<title>分页显示</title>

<!-- 第一步引入extjs的样式文件 -->

<link rel="stylesheet" type="text/css" href="ext-3.3.1/resources/css/ext-all.css">

<!-- 第二步引入extjs的库文件,底层驱动 -->

<script type="text/javascript" src="ext-3.3.1/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.3.1/ext-all.js"></script>

</head>

<body>

<div id="grid"></div>

</body>

<script type="text/javascript">

Ext.onReady(

function(){

var cm = new Ext.grid.ColumnModel([

{header:'订单Id',dataIndex:'orderId',hidden:true},

{header:'订单编号',dataIndex:'orderNo'},

{header:'订单价格',dataIndex:'price',editable:true},

{header:'创建日期',dataIndex:'createDate'}

]);

//存储器

var store=new Ext.data.Store({

proxy:new Ext.data.HttpProxy({url:"Pro_orderServlet"}),{name:'createDate'}])

});

var grid=new Ext.grid.EditorGridPanel({

renderTo:'grid',

store:store,

cm:cm,

loadMask:true,

width:600,

height:300,

bbar:new Ext.PagingToolbar({

pageSize:3,

displayInfo:true,

displayMsg:'显示第{0}{1},一共有{2}',

emptyMsg:'没有记录'

})

});

//加载存储器

store.load({params:{start:0,limit:3}});

}

);

</script>

</html>

3Ext Grid 控件的扩展功能

需求说明

在任务2的基础上,添加以下功能。

1)将分页工具栏放在面板的上方,效果如图9.2.3所示。

如图2.2.3 分页工具栏放在面板的上方

提示:tbar:new Ext.PagingToolbar...

2)添加自动行号,效果如图2.2.4所示。

图9.2.4添加自动行号

3)添加多选,效果如图2.2.5所示。

图2.2.5添加多选

4)添加排序,效果如图2.2.6所示。

图2.2.6 按订单编号降序排列

4Ext Grid 控件的删除功能

训练技能点

Ø使用 Ext Grid 控件实现删除

需求说明

(1)在上一任务的基础上,完成删除订单信息。

(2)删除订单记录的提示信息,如图2.2.7所示。

2.2.7 删除订单的提示对话框

(3)删除后,效果如图2.2.8所示

2.2.8 删除后的结果

实现步骤

(1)设计数据库表及字段。

(2)使用Servlet查询订单信息、删除订单信息。

(3)使用Ext Grid 分页显示Servlet查询数据。

(4)使用Ext删除记录。

参考代码

HTML页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>

<head>

<title>My JSP 'index.jsp' starting page</title>

<!-- 第一步引入extjs的样式文件 -->

<link rel="stylesheet" type="text/css" href="ext-3.3.1/resources/css/ext-all.css">

<!-- 第二步引入extjs的库文件,底层驱动 -->

<script type="text/javascript" src="ext-3.3.1/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.3.1/ext-all.js"></script>

</head>

<body>

<div id="grid"></div>

</body>

<script type="text/javascript">

Ext.onReady(function() {

var sm = new Ext.grid.CheckboxSelectionModel();

//定义列

var cm = new Ext.grid.ColumnModel( [ new Ext.grid.RowNumberer,sm,{

header : '订单Id',

dataIndex : 'orderId',

hidden : true

},{

header : '订单编号',

dataIndex : 'orderNo'

},{

header : '订单价格',

dataIndex : 'price',

editable : true

},{

header : '创建日期',

dataIndex : 'createDate'

} ]);

//定义存储器

var store = new Ext.data.Store( {

proxy : new Ext.data.HttpProxy( {

url : "servlet/GridServlet"

}),

reader : new Ext.data.JsonReader( {

totalProperty : 'totalProperty',

root : 'root'

},[ {

name : 'orderId'

},{

name : 'orderNo'

},{

name : 'price'

},{

name : 'createDate'

} ])

});

//创建表格

var grid = new Ext.grid.EditorGridPanel( {

renderTo : 'grid',

store : store,

cm : cm,

sm : sm,

loadMask : true,

width : 600,

height : 150,

bbar : new Ext.PagingToolbar( {

pageSize : 3,

displayInfo : true,

displayMsg : '显示第{0}{1},

emptyMsg : '没有记录',

items : [ {

text : '添加',

pressed : false

},{

text : '删除',

pressed : false,

handler : doDelete

} ]

})

});

//加载存储器

store.load( {

params : {

start : 0,

limit : 3

}

});

//批量删除开始

function doDelete() {

var array = new Array();

var strid = "";

array = sm.getSelections();//被选中的记录存储为Record对象,用其get("")方法取值

if (array.length == 0) {

Ext.MessageBox.alert("错误","没有选择数据");

} else {

Ext.MessageBox.confirm('温馨提示','你确定要删除吗?',function(btn) {

if (btn == "yes") {

for ( var i = 0; i < array.length; i++) {

store.remove(array[i]);

//获取记录中的orderId

strid += array[i].get("orderId") + ",";

}

//数据库中删除

//创建request对象

Ext.lib.Ajax.request('GET','servlet/DelSevrvlet?strid='+strid,

{

success : function(response) {

Ext.MessageBox.alert('消息','删除成功',function() {

grid.getStore().reload();

});

},

failure : function(form,action) {

Ext.MessageBox.alert('消息','删除失败!');

}

},null);

}

})

}

}

});

</script>

</html>

删除Servlet代码:

@Override

protected void service(HttpServletRequest request,IOException {

response.setContentType("text/html;charset=gbk;");

//获得删除的id

String json = request.getParameter("strid");

String[] p = json.split(",");//获得orderId数组

String orderId = "";

//循环给orderId赋值

for(String i:p){

orderId+=i+",";

}

int index = orderId.lastIndexOf(",");

orderId=orderId.substring(0,index);

Connection conn = null;

Statement stmt = null;

PreparedStatement pstmt=null;

String sql = "delete from pro_order where order_id in ("+orderId+")" ;

System.out.println(sql);

try {

conn = DBConnection.getConn();

stmt = conn.createStatement();

stmt.executeUpdate(sql);

} catch (SQLException e) {

e.printStackTrace();

}finally{

DBConnection.closeDB(conn,null);

}

request.getRequestDispatcher("GridServlet").forward(request,response);

}

巩固练习

一、选择题

1. Ext JS提供了一套强大的事件处理机制,通过这些事件处理机制可以实现的功能是( )

A. 响应用户的动作

B. 监控控件状态变化

C. 更新控件视图信息

D. 与服务器进行交互

2. Ext JS组件分类不包括( )

A. 基本组件

B. 工具栏组件

C. 菜单组件

D. 表单及元素组件

3. Ext组件可以分为( )

A. 基本组件

B. 工具栏组件

C. 扩展组件

D. 表单及元素组件

4. 在Ext组件中,window属于( )组件。

A. 基本组件

B. 工具栏组件

C. 扩展组件

D. 表单及元素组件

5. Ext表格有( )类实现。

A.Ext.grid.GridPanel

B.Ext.table.Table

C.Ext.GridPanel

D.Ext.Panel

二、简答题

1. 什么是 Ext JS?

2. Ext JS组件包括哪些?

三、操作题

使用Ext JS 的 Grid控件查询学校学生信息,实现选择一条或多条记录、高亮显示选择行、调整列宽、显示行号、支持复选框功能。

相关文章

$.AJAX()方法中的PROCESSDATA参数 在使用jQuery的$.ajax()方...
form表单提交的几种方式 表单提交方式一:直接利用form表单提...
文章浏览阅读1.3k次。AJAX的无刷新机制使得在注册系统中对于...
文章浏览阅读1.2k次。 本文将解释如何使用AJAX和JSON分析器在...
文章浏览阅读2.2k次。/************************** 创建XML...
文章浏览阅读3.7k次。在ajax应用中,通常一个页面要同时发送...