Ext JS 4.0 教程:从入门到实践
目录
-
第一部分:准备工作与环境搭建
(图片来源网络,侵删)- 1 什么是 Ext JS 4.0?
- 2 获取 Ext JS 4.0 SDK
- 3 搭建开发环境
- 4 创建第一个 "Hello, World!" 应用
-
第二部分:核心概念与架构
- 1 类系统与 Sencha Cmd
- 2 组件
- 3 布局
- 4 数据包
- 5 MVC 架构模式
-
第三部分:实战项目 - 构建一个简单的任务管理应用
- 1 项目规划与 Sencha Cmd 生成骨架
- 2 定义数据模型
- 3 创建数据存储
- 4 设计用户界面
- 4.1 主应用窗口
- 4.2 任务列表面板
- 4.3 任务表单窗口
- 5 编写控制器逻辑
- 6 整合与运行
-
第四部分:进阶主题
- 1 主题与样式
- 2 自定义组件
- 3 表单与验证
-
第五部分:总结与资源
(图片来源网络,侵删)
第一部分:准备工作与环境搭建
1 什么是 Ext JS 4.0?
Ext JS 4.0 是一个功能丰富的 JavaScript 框架,专注于构建具有桌面级用户体验的 Web 应用,它提供了:
- 丰富的 UI 组件库:如网格、表单、树、图表等。
- 强大的数据绑定:将 UI 组件与数据模型无缝连接。
- 现代化的 MVC 架构:帮助开发者组织代码,提高可维护性。
- 响应式布局:应用能自适应不同尺寸的屏幕。
2 获取 Ext JS 4.0 SDK
- 访问 Sencha Archive 页面。
- 找到 Ext JS 4.0.x 版本(4.2.1 是一个非常稳定且常用的版本),下载其 SDK(Software Development Kit)。
- 解压下载的 ZIP 文件,你会得到一个包含文档、示例和核心库文件的文件夹。
3 搭建开发环境
你需要一个简单的 Web 服务器来运行 Ext JS 应用,因为浏览器出于安全限制不允许直接从本地文件系统(file://)加载跨域的 CSS 和 JS 文件。
- 简单方法:使用 VS Code 的 Live Server 插件,或者 Python 的
http.server模块。 - 专业方法:使用 Sencha Cmd,它不仅能启动开发服务器,还能处理应用的构建和优化。
4 创建第一个 "Hello, World!" 应用
让我们创建一个最简单的页面,显示一个 Ext JS 窗口。
- 创建一个项目文件夹,
extjs-hello。 - 将 Ext JS SDK 中的
ext-all.js和ext-all.css复制到你的项目中。 - 创建一个
index.html文件,内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">Ext JS 4.0 Hello World</title>
<!-- 1. 引入 Ext CSS -->
<link rel="stylesheet" type="text/css" href="path/to/ext-4.2.1/resources/css/ext-all.css">
<!-- 2. 引入 Ext JS 库 -->
<script type="text/javascript" src="path/to/ext-4.2.1/ext-all.js"></script>
<!-- 3. 引入中文语言包 (可选) -->
<script type="text/javascript" src="path/to/ext-4.2.1/locale/ext-lang-zh_CN.js"></script>
<style type="text/css">
/* 让我们的 ExtJS 组件充满整个屏幕 */
html, body {
height: 100%;
margin: 0;
padding: 0;
border: 0 none;
overflow: hidden;
}
</style>
</head>
<body>
<!-- 4. 创建一个容器 div,Ext JS 会将组件渲染到这里 -->
<div id="hello-win"></div>
<script type="text/javascript">
// 5. 在页面加载完成后执行代码
Ext.onReady(function() {
// 创建一个窗口组件
var win = Ext.create('Ext.window.Window', {
title: '你好, Ext JS 4.0!',
width: 400,
height: 200,
html: '<h1 style="text-align:center; padding-top:50px;">Hello, World!</h1>',
renderTo: Ext.getBody() // 渲染到 body
});
});
</script>
</body>
</html>
- 使用 Live Server 打开
index.html,你应该能看到一个弹出的窗口。
第二部分:核心概念与架构
1 类系统与 Sencha Cmd
Ext JS 4 引入了基于 Ext.define 的类系统,它借鉴了经典的 Object-Oriented Programming 思想,支持继承、 mixins 和配置。
Ext.define(className, config): 定义一个新类。className: 类的完整路径,如'MyApp.view.main.MainPanel'。config: 类的配置项,包括属性、方法、extend(继承)、requires(依赖)等。
Sencha Cmd 是一个命令行工具,它极大地简化了 Ext JS 应用的开发流程:
- 生成应用骨架:
sencha generate app MyApp ./my-app - 生成类:
sencha generate model MyModel ... - 启动开发服务器:
sencha web start - 构建生产版本:
sencha app build
2 组件
Ext JS 世界万物皆组件,从按钮、面板到整个应用窗口,都是 Ext.Component 或其子类的实例。
xtype: 组件的简写别名。Ext.button.Button的 xtype 是button,在配置容器时,可以使用 xtype 来创建子组件,非常方便。- 渲染:组件需要被渲染到 DOM 中才能显示。
renderTo或autoShow等配置可以控制渲染时机。
3 布局
布局决定了组件内部子组件的排列和大小方式。
border: 经典的边框布局,将容器分为东、南、西、北、中五个区域。fit: 只显示一个子组件,并使其填满整个容器。hbox/vbox: 水平或垂直盒子布局,可以灵活地对子组件进行排列和伸缩。anchor: 子组件的大小相对于容器的百分比。
4 数据包
数据包是 Ext JS 应用的核心,它负责管理数据。
Ext.data.Model(模型):定义数据的结构,它就像一个类,定义了字段(fields)和关联(associations)。Ext.define('MyApp.model.User', { extend: 'Ext.data.Model', fields: [ { name: 'id', type: 'int' }, { name: 'name', type: 'string' }, { name: 'email', type: 'string' } ] });Ext.data.Store(存储):模型实例的集合,它负责加载、缓存、排序和过滤数据。Ext.define('MyApp.store.Users', { extend: 'Ext.data.Store', model: 'MyApp.model.User', data: [ // 本地数据 { id: 1, name: '张三', email: 'zhangsan@example.com' }, { id: 2, name: '李四', email: 'lisi@example.com' } ] });Ext.data.proxy.Proxy(代理):Store 如何获取和保存数据。AjaxProxy从服务器加载数据,MemoryProxy使用本地内存数据。
5 MVC 架构模式
Ext JS 4 推荐使用 MVC(Model-View-Controller)架构来组织代码,使项目结构清晰。
- Model (模型):定义数据结构,位置:
app/model/。 - View (视图):用户界面,包括组件、面板、窗口等,位置:
app/view/。 - Controller (控制器):处理业务逻辑,响应用户操作(如点击按钮),协调 Model 和 View,位置:
app/controller/。 - Application (应用):应用的入口,负责启动应用和加载各个部分,位置:
app.js。
第三部分:实战项目 - 构建一个简单的任务管理应用
我们将使用 Sencha Cmd 来创建一个任务管理应用,包含任务列表和添加/编辑任务的功能。
1 项目规划与 Sencha Cmd 生成骨架
-
规划:
- 模型:
Task,包含id,title,description,completed。 - 视图:
MainView:主窗口,使用border布局。TaskList:任务列表,使用grid组件。TaskForm:添加/编辑任务的表单窗口。
- 控制器:
MainController,处理“添加任务”、“编辑任务”等操作。 - 存储:
Tasks,存储任务数据。
- 模型:
-
生成骨架:
# 确保已安装 Sencha Cmd 并配置好 Ext JS SDK 路径 sencha generate app TaskManager ./task-manager cd task-manager
2 定义数据模型
在 app/model/Task.js 中:
Ext.define('TaskManager.model.Task', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int', useNull: true }, // id 可以为空,用于新建
{ name: 'title', type: 'string' },
{ name: 'description', type: 'string' },
{ name: 'completed', type: 'boolean', defaultValue: false }
]
});
3 创建数据存储
在 app/store/Tasks.js 中:
Ext.define('TaskManager.store.Tasks', {
extend: 'Ext.data.Store',
model: 'TaskManager.model.Task',
// 使用内存代理,数据存储在内存中
proxy: {
type: 'memory',
reader: {
type: 'json'
}
},
// 初始化一些假数据
data: [
{ id: 1, title: '学习 Ext JS', description: '阅读官方文档', completed: false },
{ id: 2, title: '构建示例应用', description: '创建任务管理器', completed: true }
]
});
4 设计用户界面
4.1 主应用窗口
修改 app/view/Main.js:
Ext.define('TaskManager.view.Main', {
extend: 'Ext.window.Window',
requires: [
'TaskManager.view.TaskList',
'TaskManager.view.TaskForm'
], '任务管理器',
width: 800,
height: 600,
layout: 'border', // 使用边框布局
items: [
{
xtype: 'tasklist', // 使用 xtype 引入任务列表
region: 'center' // 放置在中心区域
}
],
// ... 其他配置 ...
});
4.2 任务列表面板
在 app/view/TaskList.js 中创建:
Ext.define('TaskManager.view.TaskList', {
extend: 'Ext.grid.Panel',
alias: 'widget.tasklist', // 设置 widget xtype,方便引用 '任务列表',
store: 'Tasks', // 直接引用存储
columns: [
{ text: 'ID', dataIndex: 'id', width: 50 },
{ text: '标题', dataIndex: 'title', flex: 1 },
{ text: '描述', dataIndex: 'description', flex: 2 },
{ text: '完成', dataIndex: 'completed', xtype: 'booleancolumn', trueText: '是', falseText: '否' }
],
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [{
text: '添加任务',
iconCls: 'add',
action: 'add' // 给按钮一个 action,方便控制器捕获
}, {
text: '编辑任务',
iconCls: 'edit',
action: 'edit',
disabled: true // 默认禁用,当选中行时启用
}, {
text: '删除任务',
iconCls: 'delete',
action: 'delete',
disabled: true
}]
}],
// 为网格添加选择模型
selType: 'rowmodel'
});
4.3 任务表单窗口
在 app/view/TaskForm.js 中创建:
Ext.define('TaskManager.view.TaskForm', {
extend: 'Ext.window.Window',
alias: 'widget.taskform', '任务详情',
width: 400,
height: 300,
layout: 'fit',
modal: true, // 模态窗口
items: [{
xtype: 'form',
padding: '10 10 10 10',
defaults: {
anchor: '100%',
allowBlank: false
},
items: [{
xtype: 'textfield',
fieldLabel: '标题',
name: 'title'
}, {
xtype: 'textareafield',
fieldLabel: '描述',
name: 'description'
}, {
xtype: 'checkboxfield',
fieldLabel: '已完成',
name: 'completed'
}],
buttons: [{
text: '保存',
formBind: true, // 只有当表单验证通过时才可点击
handler: function() {
var form = this.up('form').getForm();
if (form.isValid()) {
// 保存逻辑将在控制器中处理
this.up('window').fireEvent('save', form);
}
}
}, {
text: '取消',
handler: function() {
this.up('window').close();
}
}]
}]
});
5 编写控制器逻辑
这是连接 Model 和 View 的桥梁,修改 app/controller/Main.js:
Ext.define('TaskManager.controller.Main', {
extend: 'Ext.app.Controller',
// 需要加载的视图
views: [
'Main',
'TaskList',
'TaskForm'
],
// 需要加载的存储
stores: [
'Tasks'
],
// 初始化函数,为视图中的组件添加事件监听
init: function() {
this.control({
// 监听 tasklist 中的按钮点击事件
'tasklist button[action=add]': {
click: this.addTask
},
'tasklist button[action=edit]': {
click: this.editTask
},
'tasklist button[action=delete]': {
click: this.deleteTask
},
// 监听 taskform 窗口的保存事件
'taskform': {
save: this.saveTask
},
// 监听 tasklist 的选择变化
'tasklist': {
selectionchange: this.onSelectionChange
}
});
},
// 当应用启动时,创建主窗口
onLaunch: function() {
Ext.create('TaskManager.view.Main').show();
},
onSelectionChange: function(selModel, selected) {
// 根据是否有选中行来启用/禁用编辑和删除按钮
var editBtn = Ext.ComponentQuery.query('tasklist button[action=edit]')[0];
var delBtn = Ext.ComponentQuery.query('tasklist button[action=delete]')[0];
editBtn.setDisabled(selected.length === 0);
delBtn.setDisabled(selected.length === 0);
},
addTask: function() {
// 创建一个新的表单窗口,传入一个空记录
Ext.create('TaskManager.view.TaskForm', {
title: '添加新任务',
record: Ext.create('TaskManager.model.Task') // 创建一个新的空模型实例
}).show();
},
editTask: function() {
var selected = Ext.ComponentQuery.query('tasklist')[0].getSelectionModel().getSelection()[0];
if (selected) {
// 创建表单窗口,并传入要编辑的记录
Ext.create('TaskManager.view.TaskForm', {
title: '编辑任务',
record: selected
}).show();
}
},
deleteTask: function() {
var grid = Ext.ComponentQuery.query('tasklist')[0];
var selected = grid.getSelectionModel().getSelection()[0];
if (selected) {
Ext.Msg.confirm('确认', '确定要删除这个任务吗?', function(btn) {
if (btn === 'yes') {
// 从存储中移除记录
grid.getStore().remove(selected);
}
});
}
},
saveTask: function(form) {
var record = form.record;
form.updateRecord(record); // 将表单数据更新到记录
var store = Ext.getStore('Tasks');
// 如果记录是新记录(没有id),则添加到存储
if (record.phantom) {
store.add(record);
} else {
// 如果是已存在的记录,存储会自动处理更新
store.sync(); // 在真实应用中,这里会调用后端API
}
// 关闭窗口
form.up('window').close();
}
});
6 整合与运行
- 确保你的 Sencha Cmd 项目已经生成。
- 将上述代码文件放到对应的
app目录下。 - 在项目根目录(
task-manager)下运行:sencha app build # 构建生产版本(可选,开发时可以跳过) sencha web start # 启动开发服务器
- 打开浏览器访问
http://localhost:1841(端口号可能不同),你应该能看到你的任务管理应用了。
第四部分:进阶主题
1 主题与样式
Ext JS 使用 SASS 来管理主题,你可以通过修改 resources/sass/ 下的文件来自定义颜色、字体等,然后重新编译 CSS 来改变应用的外观。
2 自定义组件
通过 Ext.define 继承现有的组件(如 Ext.panel.Panel)来创建你自己的、可复用的复杂组件。
3 表单与验证
Ext JS 提供了强大的表单功能,包括各种输入组件、VType(自定义验证类型)、Ext.form.field.VTypes 以及客户端和服务端验证。
第五部分:总结与资源
Ext JS 4.0 是一个非常强大且成熟的框架,通过其 MVC 架构和丰富的组件库,可以高效地构建复杂的商业应用。
重要提示:Ext JS 4.0 已经是一个比较老的版本,Sencha 主推的是 Ext JS 6/7,它引入了 Modern Toolkit(用于移动端和现代桌面浏览器)和 Classic Toolkit(用于传统桌面浏览器)的双包结构,虽然核心概念(如类系统、数据包、MVC)依然相通,但新版本的 API 和最佳实践有所不同,学习 Ext JS 4.0 是理解 Ext JS 思想的绝佳起点。
学习资源:
- 官方文档 (Archive): Ext JS 4.2.1 Documentation (这是最重要的资源,几乎所有 API 都有详细说明和示例)。
- Sencha Examples: Ext JS 4.2.1 Examples (查看官方示例是学习组件用法的最好方法)。
- Sencha Blog: Sencha Blog (可以找到一些关于架构和最佳实践的博客文章)。
