资讯详情

资讯详情

Sencha Ext JS 7.8+入门实战:网格、图表与表单开发指南

简介Sencha Ext JS 7.8入门指南是一份面向具备JavaScript基础、希望构建复杂企业级前端应用的开发者的PDF教程重点解决从零上手框架时面临的安装配置、项目搭建与组件创建等常见问题。内容从框架特性与优势讲起覆盖许可证获取、Sencha Command安装、npm环境管理、IDE选型、模板选择及项目文件结构等完整流程并通过数据网格、柱状图、表单捕获等典型示例帮助读者快速掌握Ext JS的UI组件体系和MVC架构。资源为单个PDF文档大小约2.65MB目前已有193人学习下载。文档按照从工具链到项目实战的次序组织配套可运行的代码片段演示视图与组件的创建过程同时列出官方文档、视频教程与社区支持等延伸资源。读者可以结合书中示例在实际项目中逐步完成调试和优化在掌握核心组件用法的同时积累企业级界面的搭建经验形成清晰的学习路径。1. 从一次选型谈起Ext JS 7.8 到底解决什么问题几年前我接手一个企业级数据管理项目前端要求表格、图表、表单混排还要支持树形导航、多标签页和复杂的权限视图。当时团队里有主张用轻量框架的也有主张自己封装组件的结果折腾到中期才发现光是搞定一个可排序、可过滤、可列显隐的表格再让它和表单联动就已经吃掉了一半工期。后来切到 Sencha Ext JS情况才真正好转。它不是给页面做点缀的UI库而是一整套面向大型应用的框架超过140个开箱即用的组件网格、图表、表单、布局全部自带数据绑定和 MVC/MVVM 架构也内置在体系里。这套《Sencha Ext JS 7.8入门指南》的价值在于它不跟你谈抽象概念直接带着从许可证获取、环境安装、项目生成一路做到底层组件落地。对写惯了类 React 或类 Vue 思路的人来说阅读它会有明显的不适感但恰恰是这种“不适感”会帮你建立起对复杂前端工程的新认知。2. 搭建环境Sencha Command 安装与项目生成2.1 两个 Toolkit 怎么选Classic 还是 Modern环境搭建之前先要弄明白 Ext JS 里的一个基础选择Toolkit。Ext JS 7.8 提供两套渲染内核共享同一个数据层和组件模型但侧重点完全不同。文档里写得很清楚Modern Toolkit 用 CSS 渲染视图优先为手机和平板优化Classic Toolkit 主要靠 JavaScript 渲染视图面向桌面浏览器上的复杂业务系统。不要被“Modern 一定优于 Classic”这种惯性带偏。对代码的掌控程度、对表格性能的追求、对现有主题的依赖才是真正的决策因素。Classic 的最大优势在于组件密度高网格的列锁定、分组表头、编辑器在桌面端表现非常成熟Modern 的布局方式更接近 Web 标准触控交互友好但某些复杂组件的支持程度需要逐项对照文档确认。这本入门指南明确把主场景放在 Classic Toolkit 上理由是它面向绝大多数企业后台的真实使用环境。我的建议是如果项目有大量表格和表单混合交互选 Classic如果是现场演示大屏、移动端优先再考虑 Modern。两者的类名略有差异但逻辑结构一致从一套切到另一套的迁移成本比你想的低。2.2 安装 Sencha Command一次只踩一半的坑Sencha Command 是后续所有操作的命令行入口创建项目、编译代码、压缩资源、启动测试服务都靠它。安装过程本身不复杂文档里有几个值得注意的细节从官网下载安装包Windows 下微软 Defender 大概率会弹警告选“仍要运行”。安装器组件选择界面不要勾 Compass 扩展那是旧版本 Ext JS 用的7.8 不再依赖它。装完以后需要确认命令行可用直接在 PowerShell 里敲一条命令验证sencha which正常输出会显示 Sencha Command 的安装路径和版本信息。常见的一个坑是环境变量没自动写入导致sencha命令找不到。解决方法是把安装目录手动加入系统 PATH再重开一个终端窗口。如果你不想走独立的安装包路径也可以选择 npm 方式管理环境。文档给出了两条官方说明链接分别对应 ZIP 安装和 npm 安装。就我的经验npm 方式更适合团队统一版本、自动拉取依赖的场景但生成项目后依然需要 Sencha Command 参与构建两者并不互斥。2.3 用一条命令生成项目装好 Sencha Command 后真正生成项目只需要一条命令。不过命令的参数结构要先搞清楚否则容易把目录生成到你不想去的地方sencha generate app classic -ext MyApp ./这条命令的参数拆开看是这样classic是 Toolkit 类型声明生成使用 Classic Toolkit 的应用。-ext表示使用 Ext JS 框架的正式版本来生成项目对比有些场景会用-ext的试玩版。MyApp是应用名称必须符合变量命名规则不能用中文、不能用数字开头。./是相对路径代表当前文件夹。执行后 Sencha Command 会拉取框架依赖生成一整套模板工程。整个过程快则几十秒慢则几分钟取决于网络和本机性能。命令执行完毕后建议先跑一次构建验证环境构建命令如下sencha app build developmentdevelopment是构建环境参数最常用还有testing和production分别对应测试验证和部署发布。这里的成功标准是终端不抛红色错误且输出里出现构建完成信息。需要留意的是生成完项目以后不要直接手动粘贴源代码进去就跑先让模板原型构建通过一次能排除很多环境层面的干扰。3. 深入模板工程目录结构、配置参数与构建3.1 模板项目里到底有哪些文件夹项目生成后第一件事是认目录。很多框架的模板工程会刻意“藏”很多东西但 Ext JS 的模板结构算是开诚布公的。一个刚生成的项目目录大致是这样的MyApp/ ├── app/ │ ├── Application.js │ ├── controller/ │ ├── model/ │ ├── store/ │ └── view/ ├── classic/ │ ├── src/ │ └── sass/ ├── modern/ ├── resources/ ├── workspace.json └── app.jsonapp/下直接对应 MVC 的各个部分Application.js 是应用入口classic/和modern/是分工具包的源码目录各自有独立的src和sassresources/存放全局静态资源app.json是全局配置文件应用ID、主题、依赖的SDK版本、启动页面等都在这定义。典型的误用是不管什么代码都往app/view/里塞。实际上store 应该跟数据模型放一起controller 单独管理事件逻辑自定义工具函数可以考虑独立目录。目录结构越清晰后边做构建时依赖分析越顺畅。3.2 app.json 里的关键配置项app.json是构建和运行的基础初学者最容易在这里翻车。文件格式是标准 JSON注释以//出现和普通 JSON 文件稍有差异。几个关键配置字段配置项作用常见调整name应用名称对应生成时传入的 ApplicationNametoolkit默认工具包可设置为 classic 或 moderntheme主题名称如 theme-triton、theme-material 等requires依赖列表需要引入的 Ext JS 组件或第三方库sdkSDK 路径指向本地 Ext JS 框架目录比较常用的是调整requires来加入图表、Excel 导出等功能模块。比如模板工程默认不带图表功能后面做柱状图视图时就需要在requires里加入图表相关的包这一点后面会详细展开。还有一个容易忽略的配置loader和loaderPath它们决定了开发模式下按需加载的机制。如果配置不对容易出现运行时突然报找不到某个类而构建阶段完全不报错的情况。3.3 构建环境的差异与运用Sencha Command 的构建命令支持三种环境参数它们的差异不只是压缩程度环境特点适用场景development不压缩、保留可读性、方便调试日常开发、断点跟踪testing模拟生产行为但保留部分调试信息测试环境、自动化验证production全量压缩、删除调试代码、优化资源正式部署我从实际经验里得到的教训是日常开发不要用production构建去验证代码逻辑压缩后的报错信息缺失严重排错成本极高。反过来上线前至少要用production构建一次完整流程才能暴露开发模式下被隐藏的依赖问题。构建完成以后输出目录在build/{environment}/{appName}/下可以直接用静态服务器托管。如果你用的是 Sencha 自带的测试服务器就不需要额外配置 Web 服务器直接执行sencha app watch会在本地启动一个开发服务器文件改动后自动编译刷新调试体验不错。4. 视图与组件实战Grid、图表、表单的三次落地4.1 MVC 架构和视图创建方式Ext JS 的 MVC 模式和常见的后端 MVC 不太一样。View 负责界面布局和组件嵌套Controller 监听组件事件并调用 Model/Store 的数据方法Model 定义字段和校验规则Store 则负责数据加载和排序过滤。这个模型中View 之间通过xtype和reference互相引用Controller 用control或listen统一管理事件绑定。视图创建有两种方式Ext.define和Ext.create。前者定义一个新的类可被复用和继承后者直接创建对象实例。两者的选择标准很简单如果这个视图会在多个地方出现或者需要被继承扩展用Ext.define如果只是临时用一次懒得起名字用Ext.create。文档里的三个练习示例数据网格、柱状图、捕获表单恰好覆盖了这三种典型场景下面逐个拆解。4.2 实战数据网格视图数据网格是企业应用里出现频率最高的组件。第一个练习的目标是在导航菜单里加入一个入口点击后展示网格视图。顺着代码走一遍会清晰很多第一步先在主视图的导航栏里加一个菜单项。导航定义通常在主视图文件里通过Ext.define声明类似这样Ext.define(MyApp.view.main.Main, { extend: Ext.container.Container, items: [{ xtype: mainlist, itemId: mainList, listeners: { select: onMainListSelect } }] });这里的mainlist是导航列表的 xtypelisteners里的select事件交给控制器里的onMainListSelect方法处理。注意事件名和回调方法名是一一对应的回调函数定义在 Controller 里不在 View 里写匿名函数这是 MVC 模式的要求。第二步创建网格视图类。网格的声明方式高度声明式每一列的行为都写在配置项里Ext.define(MyApp.view.grid.ExampleGrid, { extend: Ext.grid.Panel, xtype: examplegrid, title: Data Grid, store: { type: examplestore }, columns: [{ text: Name, dataIndex: name, flex: 1 }, { text: Email, dataIndex: email, flex: 1 }, { text: Score, dataIndex: score, width: 100 }] });列定义里dataIndex对应数据源里的字段名flex表示列宽按比例分配width则固定列宽。实际项目里我会先用固定宽度把列撑开看效果全部调通后再换成flex做响应式。第三步定义数据源。网格本身不关心数据从哪来只要 store 提供给它的数据符合字段定义Ext.define(MyApp.store.ExampleStore, { extend: Ext.data.Store, alias: store.examplestore, fields: [name, email, score], proxy: { type: ajax, url: /data/examples.json, reader: { type: json, rootProperty: data } }, autoLoad: true });alias是在整个应用里注册的短名称让 View 里可以通过type: examplestore引用。proxy负责数据源的网络层autoLoad: true表示在 store 实例化后立即加载数据。初学阶段最常见的错误是忘了给 store 设置alias导致 View 里引用时找不到对应类。网格除了展示还有几个值得默认打开的交互项。列头的排序只需在列配置中加sortable: true如果要支持列显隐和拖拽调整宽度需要在Ext.grid.Panel配置项里打开对应功能Ext.define(MyApp.view.grid.ExampleGrid, { extend: Ext.grid.Panel, xtype: examplegrid, enableColumnHide: true, enableColumnMove: true, columnLines: true, // 其他配置... });enableColumnHide开启列显隐菜单enableColumnMove允许拖拽列头调整顺序columnLines控制表格列间的分割线。这些都是企业后台几乎必须开启的选项。网格工具栏里的筛选功能属于另一个大话题原理是在 store 上挂 filter网格组件本身不负责筛选逻辑。4.3 实战柱状图视图图表功能的激活路径和网格差别很大。模板工程默认不打包图表组件需要先在app.json的requires里加入对应依赖这一步不做后边引用图表类会直接报“找不到类”的错误。在app.json的 requires 数组中加入requires: [ Charts ]实际配置时依赖名字要跟 SDK 版本里的包名严格一致如果不确定可以先在项目根目录执行sencha package list查看当前环境里有哪几类包避免写错包名导致构建失败。图表类的定义方式和网格高度类似核心区别在于 axes 和 series 的配置Ext.define(MyApp.view.chart.ExampleChart, { extend: Ext.chart.CartesianChart, xtype: examplechart, width: 100%, height: 400, store: { type: chartstore }, axes: [{ type: numeric, position: left, title: Value, fields: [value] }, { type: category, position: bottom, title: Category, fields: [name] }], series: [{ type: bar, xField: name, yField: [value], style: { fill: #4A90D9 } }] });axes里numeric是数值轴category是分类轴series里的type: bar声明这是个柱状图xField和yField决定横轴和纵轴对应的数据字段。这里有一个新手高频错误yField的值是数组如果你写成字符串图表能渲染但数据不上轴。图表绑定数据的 store 和普通 store 没有本质区别只是字段要跟xField、yField匹配。你可以使用静态数据模拟也可以像之前网格示例那样通过 proxy 从接口拉取。开发阶段我个人习惯先用静态数组把图表的配置跑通再接真实接口这样排错范围会明显缩小。4.4 实战捕获表单表单是三个练习里交互逻辑最重的因为涉及字段值读取、校验、提交三件事。表单视图的写法比网格更接近传统 HTML 表单只不过封装得更深Ext.define(MyApp.view.form.ExampleForm, { extend: Ext.form.Panel, xtype: exampleform, title: Capture Form, bodyPadding: 16, items: [{ xtype: textfield, name: username, fieldLabel: Username, allowBlank: false }, { xtype: numberfield, name: age, fieldLabel: Age, minValue: 0, maxValue: 120 }, { xtype: combobox, name: department, fieldLabel: Department, store: { type: departmentstore }, queryMode: local, displayField: name, valueField: id }], buttons: [{ text: Submit, formBind: true, handler: onSubmitForm }] });allowBlank: false在 textfield 上声明该字段不能为空formBind: true时提交按钮会根据表单校验状态自动禁用。这个机制很实用不用手写校验逻辑就能获得基础的提交前验证。handler: onSubmitForm是事件方法名定义在对应的 Controller 里。Controller 侧的表单处理逻辑同样简单Ext.define(MyApp.controller.FormController, { extend: Ext.app.ViewController, alias: controller.formcontroller, onSubmitForm: function () { var form this.lookupReference(form); if (form.isValid()) { form.submit({ url: /api/submitForm, success: function () { Ext.Msg.alert(Success, Form submitted); }, failure: function () { Ext.Msg.alert(Error, Submit failed); } }); } } });表单数据量较小时把表单直接读取为普通对象再用 Ajax 提交也很常见。form.getValues()会把当前表单所有字段的值收集为一个对象。不过需要留意getValues()拿到的只是表单字段值不是序列化后的完整请求参数后端接口字段名对不上时排查起来会很费劲建议提交前用日志把值打出来确认一遍。4.5 避坑组件创建的三个高频问题第一个坑是“类找不到”。现象是运行时报错Cannot read properties of undefined (reading xxx)或者直接提示缺少某个类。原因通常有两种一是Ext.define里声明的xtype没有被自动加载二是在app.json里漏了依赖声明。解决方法是检查requires配置确认依赖包名称正确然后在开发模式下重新构建。第二个坑是 store 没有autoLoad导致页面空白表格。现象是网格组件渲染正常但没有数据行。原因不是写错字段而是 store 实例还没加载完成就开始消费数据。解决方法是给 store 配置autoLoad: true或者 view 里显式调用store.load()。第三个坑是表单验证不触发。现象是填了非法值按钮却仍然可点。原因往往是跳过了formBind: true或者字段在校验前就被赋了初始值导致 valid 状态没有更新。解决方法是确认按钮开启formBind并且在字段change事件里主动调用form.isValid()刷新状态。这些坑在文档示例里不会直接告诉你但在把练习项目从模板改造成真实业务组件时出现的频率几乎百分之百。5. 避坑指南许可证、构建与环境配置的五个教训5.1 许可证激活失败现象是执行sencha generate app时提示许可证无效或未激活项目生成到一半中止。原因多为登录信息未同步到本机或试用的许可证已经过期。解决方式是重新运行sencha license相关命令完成认证再确认当前使用的 Ext JS 版本和许可证类型匹配。不要尝试直接用破解或绕过机制这既不符合合规要求也容易让后续升级寸步难行。5.2 依赖包版本冲突导致构建失败现象是构建到一半终端报一堆版本冲突或者类重复定义的错误。原因是项目里引用的第三方包和 Ext JS 内置模块之间存在同名的类或样式文件。解决方法是先定位是哪个requires引入的包出问题再调整依赖顺序必要时把冲突的包升级到与 SDK 匹配的版本。这类问题隐蔽建议每添加一个依赖后单独构建一次而不是攒到最后统一构建。5.3 开发模式下正常、生产模式构建报错现象是sencha app build development一切正常切换到sencha app build production就报错。原因是代码里依赖了开发模式独有的资源或者路径比如开发模式下自动生成的临时文件生产构建时会被清掉。解决方式是检查是否有硬编码相对路径、依赖了resources目录下随环境变化的文件统一改成通过app.json或构建变量引用。5.4 修改主题后样式没有生效现象是改了 Sass 变量或主题配置构建后页面样式没变化。原因是主题变更需要触发完整重新构建增量编译不一定覆盖所有使用该变量的组件。解决方式是执行一次干净的构建sencha app clean sencha app build developmentclean会清掉旧的构建产物然后再全量重建基本能解决大多数样式不更新问题。5.5 本地开发环境与团队其他成员不一致现象是同一套代码在不同人机器上构建结果不一样。原因是 Sencha Command 或 SDK 版本存在差异npm 依赖也可能被锁定到不同版本。解决方式是在项目根目录维护一份依赖/版本说明文件明确 SDK 版本和 Command 版本并在代码仓库里固化构建脚本。团队协作时不要手动从官网站点下载 SDK 覆盖到本地目录尽量统一走同一个安装流程。6. 进阶实践模板项目改造为真实工程的两个技巧6.1 用sencha app watch提升开发效率如果你还在每次改代码后手动执行构建命令强烈建议切换到sencha app watch模式。它会监听源码目录的文件变更自动触发增量编译并在本地启动一个开发服务器。整个过程基本是秒级反馈改完 store 字段、调整列宽保存后刷新浏览器就能看到新结果。使用方式很简单在项目根目录执行sencha app watch执行后终端会输出本地访问地址浏览器打开即可预览效果。注意watch模式下日志会有大量输出不要看到一条警告就紧张只要页面能正常渲染就没问题。如果改动后页面没有更新先确认文件保存路径在app/或classic/src/下放在resources/或项目根目录的文件不一定会触发监听。搭配浏览器开发者工具一起用可以省掉很多不确定的排错时间。我自己惯用的流程是代码保存后先在终端看构建日志有没有报错没有报错再切到浏览器刷新刷新后页面有问题直接打开控制台定位到具体的代码文件和行号。这套顺序走顺了多数问题能在两分钟以内锁定范围。6.2 用Ext.define把复用组件沉淀下来模板工程里的代码结构偏向“演示型”所有视图都平铺在 view 目录下。真实项目里会有多个页面要用到同一个 Table 组件或者同一个字段组合在不同表单里反复出现。这时一定要把复用逻辑沉淀成独立的类。一个简单例子把带筛选功能的网格封装为一个可复用的组件Ext.define(MyApp.view.common.FilterGrid, { extend: Ext.grid.Panel, xtype: filtergrid, config: { filterable: true }, initComponent: function () { var me this; if (me.getFilterable()) { me.tbar [{ xtype: textfield, emptyText: Filter..., listeners: { change: function (field) { var store me.getStore(); store.clearFilter(); store.filter(me.getFilterProperty(), field.getValue()); } } }]; } me.callParent(); } });这段代码的思路是把筛选输入框塞进网格自带的工具栏filter时按指定属性过滤当前 store而 view 的使用方只需要设置filterable: true和filterProperty就能在任意页面复用一套带筛选功能的网格。等到这个组件被两三个页面同时引用了你就能真切体会到 Ext JS 这套“声明式继承 配置化复用”的设计价值。还有一个小技巧自定义组件发布到团队内部时一定要给它一个规范化的xtype命名比如统一定义前缀wt-这样使用方通过xtype引用即可不必关心完整的类名路径团队内部协作时彼此都不会误解。无论是做数据后台、报表系统还是内部管理系统Ext JS 7.8 的学习曲线都陡峭在“框架自己的思考和范式”上而不是 JavaScript 语法本身。跟着文档把网格、图表、表单三个示例完整落地一遍再回头看自己手头项目的需求思路会清晰很多。那次做完选型切换以后我把这套“先跑通模板、再改造组件、最后沉淀公共类”的顺序固定成了团队里的标准动作每次接手新的 Ext JS 项目都强制走一遍省下的返工时间远远超过初期的学习成本。希望这些踩坑记录能让你少走一段弯路也希望这套入门资料能成为你构建复杂企业应用的稳定起点。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →