ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Sencha Ext JS 7.8环境搭建与组件开发:Cmd安装、构建与排错

Sencha Ext JS 7.8环境搭建与组件开发:Cmd安装、构建与排错

简介:面向具备一定 JavaScript 基础、希望构建企业级复杂前端应用的开发者,这份 Sencha Ext JS 7.8+ 入门指南聚焦安装、模板与组件创建,帮助读者从许可证获取、环境配置走到基础项目搭建,并理解框架在 MVC 架构、数据可视化与 UI 组件上的特点。压缩包共 1 个 PDF 文件,大小约 2.65MB,适合集中阅读和随查随用。正文覆盖试用版与商业许可项目流程、Sencha Command 安装、npm 环境管理、IDE 选择、项目文件结构,以及数据网格、柱状图、表单捕获等示例,并配有代码和操作步骤,可对照完成调试与优化。文档还从框架特点与工具包差异切入,依次说明项目创建、构建流程与基础模板导航,便于按章节实践和查漏补缺。已有 196 人学习,适合需要快速上手 Ext JS、积累企业级前端项目实践经验的初中级开发者。

1. 装 Sencha Ext JS 7.8 之前先想清楚:Classic 还是 Modern,这决定了后面所有命令

有个前端同事按 Sencha Ext JS 7.8 的入门指南敲完sencha generate app,直接双击index.html,浏览器一片白,控制台安静得像没加载过。原因不复杂:这套框架不是引一个 script 标签就能跑的东西,它要先装 Sencha Command、生成项目骨架、再 build 一次,少任何一步页面都是空的。Sencha Ext JS 的定位很明确,JavaScript 写视图、MVC 架构拆代码、Grid 和 Chart 撑数据可视化,140 多个现成组件摆在那里,企业级后台项目用得多。装不顺的时候,报错往往只有一句通用提示,新手卡两天很正常。

2. 安装 Sencha Command:7.8.0 的下载、安装器选项和 npm 备选路线

Ext JS 本身只是一个框架包,真正让你能敲命令的是 Sencha Command(下文简称 Sencha Cmd)。它负责创建、压缩、构建、测试应用,是整个环境的地基。地基装歪了,后面generate app、app build都会以各种奇怪的方式失败,所以这一章先把安装器、许可证、npm 三条路走清楚。

2.1 拿许可证的两条路:试用版和商业版差在哪

Ext JS 7.8 的入门文档是从「先获得一个有效许可证」开始的,这个顺序别跳过。试用版走官网的 Download Trial 页面,填一份基本信息,提交后就能进到下载面板;商业版则是先激活再下载安装。两个版本装出来的 Sencha Cmd 是同一套命令行,差别主要体现在可用模板和部分工具上。

下载面板里通常不止一个东西,除了 Sencha Command,还能看到 Sencha Architect(低代码可视化编辑器)、Sencha Themer(主题设计工具)、Rapid Ext JS(编辑器插件,带属性检查器)以及 ReExt(把 Ext JS 组件塞进 React 项目的桥接件)。我一般建议第一次只下 Sencha Command,别贪多。多装一个工具不会让环境更完整,只会让排错时多一层变量——出问题时你得先判断是 Cmd 的问题还是插件的问题。

试用版项目在功能上足够跑通网格、图表、表单这三类组件,适合先验证环境通不通。等确认团队要上,再走商业版的激活流程,那时候项目结构、命令基本不用改,只是模板选项多了几个。

2.2 安装 Sencha Command:那个 Compass 勾选项别手滑

拿到底层安装包之后,流程不复杂,但有两个地方年年有人翻车。

# 1. 下载 Sencha Command 安装包后解压 # 2. 双击安装器,按向导下一步 # 3. 到达 "选择组件" 界面时,Compass 扩展不要勾 # 4. 安装完成后,必须重开一个终端窗口,PATH 才会刷新 where.exe sencha sencha -v

第一步到第三步是安装器交互,没有命令行可写,但第四步这两行命令非常关键。where.exe sencha在 Windows 上查的是命令实际解析到的路径,sencha -v输出的是 Sencha Cmd 自己的版本号。两行都过了,才算装上了。老版本终端会话不会重新读取安装器写进去的环境变量,所以装完不重开窗口,八成会得到「sencha 不是内部或外部命令」——这个问题太常见了,几乎每个新人的第一封求助消息都是它。

Compass 这一项要单独说。它是早期 Ext JS 版本用来编译 Sass 的扩展,7.8.0 已经不需要了。安装器里如果你顺手勾上,装是能装完,但后续构建阶段可能冒出一堆和 Sass 编译相关的杂音,排查起来很浪费时间。安装向导里看到它,直接跳过。

注意:Windows 上运行安装器时,系统自带的防护可能会弹窗拦一下,界面上的处理方式是选择仍然运行,继续安装即可,不用去关掉整个防护。

2.3 用 npm 管环境,以及装完的版本自检清单

有些团队不希望往系统里塞一个全局安装器,倾向用 npm 统一管理工具链。这条路是官方支持的,文档里对应「Getting Started with NPM」那一篇,思路是把 Sencha 相关的命令行工具当普通全局包来装。

# 先确认 Node 环境存在,Ext JS 7.x 的工具链对 Node 版本有要求 node -v npm -v # 查看当前全局装了哪些包,避免和已有版本冲突 npm ls -g --depth=0

node -v和npm -v是前置检查,Node 版本太老会导致全局安装脚本跑不起来。npm ls -g --depth=0只列一层,输出干净,能一眼看到机器上是不是已经有一个旧版 Sencha 工具占着位置。

这里我要提醒一句:全局包的包名和版本号,别照着两三年前的博客抄。Ext JS 的工具链在不同小版本之间改过包名,抄错了要么装上一个不存在的包,要么装上一个和 7.8 不匹配的旧包,后者更难查——命令能跑,生成的项目却编不过。以官方 npm 文档给的包名为准,装完立刻sencha -v验证。

装完之后的检查清单我固定用这张表,每次新机器都过一遍:

检查项命令期望结果
命令是否在 PATHwhere.exe sencha(Linux/macOS 用which sencha)输出一个真实路径
版本是否正确sencha -v输出 7.8 对应的 Cmd 版本
Node 是否可用node -v输出 LTS 版本号
npm 全局是否干净npm ls -g --depth=0没有重复的旧版工具包
终端是否刷新新开一个窗口再跑一遍命令仍可用

这张表看着啰嗦,但它把「装完了」和「装对了」分开了。很多人卡在第二步却以为是第四步的问题,来回折腾环境变量。

另外提一句 Java。Sencha Cmd 底层依赖 Java 运行时,安装器一般会一并处理掉,日常不用管。但如果你的机器上同时装过好几个 Java 版本,构建阶段报出和 Java 相关的错误,第一个要看的是JAVA_HOME指向哪个版本,而不是重装 Cmd。这是我踩过一次的坑,重装了三遍才发现是环境变量指错。

到这里环境层就算立住了。接下来的事都在项目目录里发生。

3. 生成第一个项目:sencha generate app 的参数、模板和目录结构

命令能用了,下一步是生成项目。这一步看着只有一行命令,参数却有三个位置容易写错,写错了不会报错,只会生成一个结构奇怪、后面越用越别扭的工程。

3.1 先把目录和 toolkit 定死:classic 还是 modern

Ext JS 有两个 toolkit,共用同一套内核,但优化方向不同。Modern Toolkit 主要靠 CSS 渲染视图,面向平板、手机这类移动设备优化;Classic Toolkit 主要靠 JavaScript 渲染,面向桌面端 Web 应用优化。文档在这一段特意强调了一句:这只是优化侧重点,不是硬限制,Classic 也能跑在移动设备上,Modern 也不是只能做手机页面。

选择依据是项目本身。后台管理系统、数据密集的表格页、复杂的桌面端表单,选 classic;要做触屏优先的现场采集、移动端查看,选 modern。这份 7.8 的入门材料自己是以 Classic Toolkit 为主线的,网格、图表、表单三个示例都按 classic 走,所以第一次跟做,建议直接 classic,别中途换。

开工前先建目录。目录位置有讲究:用 Sencha 自带的测试服务器,放哪都行;如果最终要放到商业 Web 服务器上,得先看那台服务器的目录规范,别生成完了再搬。

# 建项目目录并进入 New-Item -ItemType Directory -Force -Path D:\SenchaProject\MyApp | Out-Null Set-Location D:\SenchaProject\MyApp # 确认当前目录,避免在父目录生成一堆东西 Get-Location

New-Item -Force的好处是目录已存在也不会报错,适合写在脚本里反复执行。Get-Location这行是我自己的习惯,生成项目前一定确认当前路径,因为下一条命令的输出目录参数写的是相对路径./,位置错了东西就撒在别处了。

3.2 sencha generate app 三个参数逐项拆

生成命令的完整形态是这样:

# 通用形态 sencha generate app [toolkit] -ext [ApplicationName] [Folder/Directory] # 实际用的例子:在当前目录生成一个名为 MyApp 的 classic 项目 sencha generate app classic -ext MyApp ./

三个参数逐个看。第一个[toolkit]填classic或modern,决定生成哪套视图基类和主题;第二个-ext后面跟应用名,必须符合变量命名规则,用大驼峰,别带横线、空格和数字开头;第三个是输出目录,./表示当前目录,也可以写./webapp这种相对路径生成到子目录。

第三条最容易出错的地方在应用名。有人图省事写成my-app,命令可能不报错,但生成出来的类名、命名空间全带上了非法字符,后面Ext.define一写就崩。应用名就是命名空间,老老实实用MyApp、AdminPortal这种。

执行完,当前目录会出现一套骨架。第一次看会有点懵,我按重要性排一下:

路径作用你会不会改
app/应用代码根目录天天改
app/view/视图类,面板、网格、图表都放这天天改
app/store/数据源定义经常改
app/model/数据模型按需
app.json应用级配置,包依赖、构建参数偶尔改,改错影响全局
build/构建产物输出不改,看结果
resources/静态资源偶尔
index.html入口页基本不动
.sencha/、workspace.jsonSencha Cmd 的工作区与构建配置不动

app.json值得单独提一句,它是 Cmd 读的配置文件,加包依赖、调构建输出目录都在这。改它的时候建议一次只改一项,改完立刻构建,别攒一堆改动一起构建——出问题时你不知道是哪一项引起的。

3.3 生成完必须 build:三个环境别选错

文档里有一句被我划了重点的话:项目生成之后,必须构建才能正常使用。这是 Ext JS 和很多脚手架最大的差别,也是白屏问题的总根源。它的视图是运行时按类声明动态渲染的,不经过一次构建,index.html里引的依赖清单是不完整的。

构建命令只有一条,后面跟环境名:

# 开发环境:带完整调试信息,产物体积大,改代码后重建快 sencha app build development # 测试环境:介于中间,给 QA 或联调用 sencha app build testing # 生产环境:压缩、合并,产物可直接部署 sencha app build production

三个环境的差别不只是体积。development 保留了完整的类名和调试信息,浏览器里看调用栈能对到源文件行号;production 会做压缩和合并,类名被压短,报错信息基本没法看。所以生产环境出的问题,一律回到 development 环境复现,别对着压缩后的代码猜。

日常开发中我一般会开 watch,改完文件自动增量构建,比手动重复敲 build 舒服:

# 监听文件变化并自动重建,同时起一个本地开发服务 sencha app watch

sencha app watch会占住一个终端窗口,别关。它是增量构建,第一次启动稍慢,后面每次改动都是秒级响应。新手常犯的错是改完代码直接刷新浏览器,发现没变化就怀疑人生——其实是没构建。开着 watch,这个坑自动绕过去了。

3.4 骨架里第一个要改的文件:导航

生成的默认模板自带一个主视图和配套的 Model、View Controller,通常在app/view/main/下。默认导航是一个左侧菜单加一块内容区,你要做的第一件事就是把菜单项换成自己的页面入口。

改法很直接:找到主视图里的菜单配置,往items里加一项,xtype指向你后面要写的视图,handler指向控制器里的方法名。这一步先别急着写业务组件,就把菜单项加进去、构建、看菜单是否出现。导航通了,说明「菜单 → 控制器 → 视图」这条链路是活的,后面加组件只是往里填东西。

提示:改完菜单先构建一次再点,别在浏览器里硬刷新等它自己变。

4. 组件落地:Ext.define 与 Ext.create,以及网格、图表、表单三件套

环境通了,项目骨架也有了,接下来才是真正写代码。Ext JS 的组件写法有一套固定套路,摸清Ext.define和Ext.create的区别,后面三个示例就都是一回事。

4.1 Ext.define 与 Ext.create:声明和实例别搞反

Ext JS 的视图创建是声明式写法,对象化架构之上跑 MVC 或 MVVM。这两个方法名字像,职责完全不同。

Ext.define是声明一个类,告诉框架「有这么一种视图,它长这样」,此时不产生任何界面;Ext.create是拿一个已经声明过的类,实例化出一个真实对象,挂到页面上。

// 声明:定义一个类,继承自 Panel,注册 xtype 方便被其他组件引用 Ext.define('MyApp.view.demo.DemoPanel', { extend: 'Ext.panel.Panel', // 父类 xtype: 'demopanel', // 别名,别处用 xtype 引用它 title: '演示面板', html: '这是一个通过 Ext.define 声明的视图' }); // 实例化:真正创建对象并渲染到 body Ext.create('MyApp.view.demo.DemoPanel', { renderTo: Ext.getBody() // 指定挂载点 });

extend决定继承链,xtype是延迟实例化的关键:你在别的容器里写{ xtype: 'demopanel' },框架会在需要渲染时才去创建它,页面里几十个组件也不会一次性全实例化。renderTo只在最外层用一次,容器内部的子组件靠items配置自动挂上去,不要再写renderTo,写了会出现重复渲染或者挂错父容器。

这个区别值得记牢,因为新手最常见的写法错误就是在视图类里直接Ext.create出一个子组件挂上去,导致每次父容器渲染都新建一个实例,内存里堆一堆孤儿对象。

4.2 数据网格:ExampleStore 加 Grid View 的最小闭环

网格是 Ext JS 最有代表性的组件,也是企业后台用得最多的。一个能跑的网格需要两半:Store 提供数据,View 负责展示。

先写 Store:

// app/store/ExampleStore.js Ext.define('MyApp.store.ExampleStore', { extend: 'Ext.data.Store', alias: 'store.examplestore', // 注册 store 别名 fields: [ { name: 'name', type: 'string' }, { name: 'value', type: 'int' } ], data: [ // 示例数据,真实项目换成 proxy 拉接口 { name: '华北', value: 128 }, { name: '华东', value: 216 }, { name: '华南', value: 174 }, { name: '西南', value: 92 } ] });

fields定义字段名和类型,类型写对很重要,int类型的列排序才是数值排序,写string会变成字典序,9排在100后面。alias里的store.examplestore是约定写法,引用时只写后半段examplestore。data是内联数据,正式项目里换成proxy配置指向后端接口,字段定义不用改。

再写网格视图:

// app/view/grid/ExampleGrid.js Ext.define('MyApp.view.grid.ExampleGrid', { extend: 'Ext.grid.Panel', xtype: 'examplegrid', title: '区域数据', store: { type: 'examplestore' }, // 按别名取 store,框架自动实例化 columns: [ { text: '区域', dataIndex: 'name', flex: 1 }, { text: '数量', dataIndex: 'value', width: 120, align: 'right' } ], features: [{ ftype: 'filters', // 列头筛选 encode: false, local: true // 前端本地筛选,数据量小的时候够用 }], tbar: [{ text: '刷新' }] });

store: { type: 'examplestore' }这种写法比Ext.create干净,框架会按需创建并在销毁时回收。列配置里flex: 1让这一列吃掉剩余宽度,width是固定宽,两者混用可以做出「一列自适应、其余固定」的效果。features里的filters是列筛选功能,local: true表示在浏览器端过滤,数据量上万条就要改local: false走服务端,否则首屏会卡。

tbar是顶部工具栏,按钮的 handler 建议挂到控制器方法上,写法是字符串形式的方法名,别直接写匿名函数——匿名函数在视图类里写多了,逻辑就散在视图里,后期改一个交互要翻遍视图文件。

把这个网格接到主界面的菜单上,点菜单出标签页,这一步跑通,数据可视化的第一块就有了。

4.3 柱状图:ChartStore 和 ExampleChart 的接线方式

图表比网格多一步:要确认图表功能所在的包已经加载进来。默认模板不一定带图表包,构建时报缺少图表包,就去app.json的依赖列表里补上,然后重新构建。不同小版本之间包名可能有细微差别,以构建报错提示的包名为准,别硬猜。

数据侧照旧是一个 Store:

// app/store/ChartStore.js Ext.define('MyApp.store.ChartStore', { extend: 'Ext.data.Store', alias: 'store.chartstore', fields: ['month', 'total'], // 不写 type 默认按自动推断,图表轴用它 data: [ { month: '1月', total: 42 }, { month: '2月', total: 58 }, { month: '3月', total: 31 }, { month: '4月', total: 76 } ] });

图表视图的配置分成三块:坐标轴、系列、外框。

// app/view/chart/ExampleChart.js Ext.define('MyApp.view.chart.ExampleChart', { extend: 'Ext.chart.CartesianChart', xtype: 'examplechart', store: { type: 'chartstore' }, insetPadding: 32, // 图表四周留白,太小吃掉标签 axes: [{ type: 'numeric', // 数值轴,放 Y position: 'left', fields: ['total'], title: '总量' }, { type: 'category', // 类目轴,放 X position: 'bottom', fields: ['month'] }], series: [{ type: 'bar', xField: 'month', yField: 'total', style: { opacity: 0.85 }, label: { display: 'insideEnd', field: 'total' } }] });

axes里fields必须和 Store 的字段名严格一致,写成value而 Store 里叫total,图表不报错,就是一片空白——这个坑非常隐蔽,我第一次遇到时盯着浏览器控制台看了半小时。series的xField对应类目轴字段,yField对应数值轴字段,两个轴的fields和这里的配置要对得上。insetPadding别设太小,否则左侧刻度标签会被裁掉。

坐标轴类型也容易选错:时间序列数据要用type: 'time'并配dateFormat,用category会把每个时间点当成独立类目,间距全乱。

4.4 表单与控制器:Capture Form 的提交链路

第三个组件是表单,它比前两个多出一个控制器,链路也更完整:视图负责字段布局,控制器负责校验和提交。

// app/view/form/CaptureForm.js Ext.define('MyApp.view.form.CaptureForm', { extend: 'Ext.form.Panel', xtype: 'captureform', controller: 'captureform', // 关联控制器别名 title: '信息采集', bodyPadding: 16, defaults: { anchor: '100%', labelWidth: 90 }, items: [ { xtype: 'textfield', name: 'name', fieldLabel: '名称', allowBlank: false }, { xtype: 'numberfield', name: 'age', fieldLabel: '数值', minValue: 0 }, { xtype: 'combo', name: 'dept', fieldLabel: '分类', store: ['研发', '运维', '测试'], queryMode: 'local', editable: false } ], buttons: [ { text: '提交', formBind: true, handler: 'onSubmit' } ] });

allowBlank: false是必填校验,formBind: true让按钮跟随表单有效性自动启用或禁用,minValue限制数值下界。combo的queryMode: 'local'配数组数据源可以直接用,配后端数据源则要改成remote并定义 proxy,改错了下拉框会一直是空的。

控制器:

// app/view/form/CaptureFormController.js Ext.define('MyApp.view.form.CaptureFormController', { extend: 'Ext.app.ViewController', alias: 'controller.captureform', // 和视图里的 controller 对应 onSubmit: function () { var view = this.getView(); if (!view.isValid()) { // 双保险,按钮禁用状态也可能被绕过 Ext.Msg.alert('提示', '请先补全必填项'); return; } var values = view.getValues(); // 真实项目在这里换成 Ext.Ajax.request 提交到后端 Ext.Msg.alert('已采集', Ext.encode(values)); } });

alias: 'controller.captureform'和视图里的controller: 'captureform'是一对,写错一边,按钮点了没反应且不报错。this.getView()拿到关联的视图实例,比用Ext.ComponentQuery去查组件可靠得多。isValid()那一层判断不是多余,表单校验是异步的,按钮状态在某些快速操作下会被绕过。

MVC 在 Ext JS 里就是这么落的:Model 管数据结构,View 只管长什么样,Controller 里写交互。三个示例走下来,套路是同一个——定义类、给别名、用 xtype 装配、逻辑放控制器。

5. 排查清单:Sencha Cmd 从安装到构建的 5 个高频翻车现场

前四章是顺风局,这一章是翻车记录。这几个问题在我经手的环境里反复出现,每一个都按「现象、原因、解决」写清楚,照着对照基本能自己定位。

5.1 现象:命令行提示 sencha 不是内部或外部命令

原因基本只有两个:安装器没把路径写进系统环境变量,或者你用的还是安装之前就开着的那个终端窗口。前者在极少数自定义安装目录的情况下出现,后者是绝大多数。

解决顺序是先重开窗口,再查路径,最后才考虑重装。

# 新开一个 PowerShell 窗口后执行 where.exe sencha $env:PATH -split ';' | Select-String -Pattern 'Sencha'

第一条查到路径就说明环境变量没问题,问题只是旧窗口。第二条从 PATH 里筛出 Sencha 相关目录,能确认安装器写进去的路径对不对。如果两条都空,去系统环境变量里手动补上 Sencha Cmd 的安装目录再重开窗口。别急着重装安装器,重装一遍还得重开窗口,白折腾。

5.2 现象:Windows 上安装器被防护软件拦住,或者装完构建报 Sass 相关错误

拦截这一条,界面上选择仍然运行即可继续,不需要关掉整套防护。装完构建报 Sass 编译错误,八成是安装组件界面里勾了 Compass 扩展——那是早期版本用的东西,7.8.0 不需要。

解决方式是重跑安装器,在组件选择页面把 Compass 取消勾选,然后重新构建。如果报错信息里出现和 Sass、Compass 相关的字样,先怀疑这个勾选,别去改项目的样式文件,改那儿没用。

注意:重跑安装器前先关掉所有占用 Sencha Cmd 的终端和编辑器进程,否则文件被占用会导致覆盖安装不完整。

5.3 现象:generate app 成功,浏览器打开 index.html 一片空白

这是最高频的一个。原因就一句话:没构建。项目生成只产出了源码骨架,index.html依赖的类清单和环境配置要靠构建生成,跳过 build 直接打开文件,框架根本加载不起来。

解决:

# 在项目根目录执行,不要进到 app 子目录 sencha app build development # 或者直接开监听,边改边构建 sencha app watch

命令必须在项目根目录执行,就是含app.json的那一层。跑到app/里执行会提示找不到应用配置。构建成功后在浏览器打开开发服务地址,而不是双击文件——直接用file://协议打开,部分资源加载会被浏览器策略挡住,看起来也像白屏。

5.4 现象:production 构建完成,部署后样式丢失、图片 404

原因通常是部署时把整个项目目录当成了网站根目录。生产构建的产物在build/production/下面的应用名目录里,真正的站点根是那一层,不是项目根。

解决方式是把build/production/MyApp(换成你的应用名)作为站点根目录部署,用静态服务器验证一下:

# 临时起个静态服务,把生产产物目录当根 cd build/production/MyApp python -m http.server 8080

访问http://localhost:8080看资源是否都能加载。这一步能在交付前把路径问题全部暴露出来。另外,如果应用部署在子路径下,app.json里的构建输出配置要跟着调,否则资源引用还是从根开始找。

5.5 现象:组件类找不到,或者界面渲染成另一副样子

十有八九是 classic 和 modern 混用了。两个 toolkit 共享内核,但类名和主题并不完全一致,在 classic 项目里引用 modern 专有的类,构建阶段不一定报错,运行时才炸。

判断方法很直接:看项目生成时用的哪个 toolkit,再检查视图基类。classic 项目的网格基类是Ext.grid.Panel, modernist 的写法不一样。跨 toolkit 抄代码是这类问题的常见来源,网上示例不一定标注用的是哪套。

解决方式是统一 toolkit,跨项目的代码片段先确认来源再抄。真要两套都用,就建两个项目分别维护,不要在同一个工程里混着写。

6. 装完怎么验证跑通:一条从 generate 到 production 的验收路径

环境装完不算完,得有一条能反复执行的验收路径。我习惯按下面这张表从头走到尾,任何一步对不上就回去查对应章节,别跳步。

验收点操作通过标准
命令层sencha -v输出 7.8 对应版本号
生成层sencha generate app classic -ext MyApp ./目录里出现app/、app.json
构建层sencha app build development终端无 ERROR,产物出现在build/
运行层sencha app watch后访问本地服务首页正常渲染,菜单可点
组件层依次点开网格、图表、表单标签网格有数据、图表有柱、表单校验生效
交互层在表单里空着必填项点提交按钮禁用或弹出提示,不会静默提交
生产层sencha app build production后用静态服务验证样式完整、无 404

组件层的验证有个小技巧:先验证数据,再验证渲染。网格没数据先看 Store 的data有没有内容,再看columns的dataIndex和fields对不对得上;图表空白同理,先确认 Store 有数据,再查axes和series的字段名是否一致。绝大多数「组件不显示」都是字段名对不上,而不是组件本身的问题。

生产层验证完,再做一次清理构建,确认不是靠缓存糊过去的:

# 清理后重新构建,排除增量构建残留的干扰 sencha app build --clean production

--clean会清掉之前的构建缓存重来一遍,慢一些,但能暴露「本地能跑、换台机器就崩」的隐性问题。交付前我必定跑一次这个,比任何口头确认都管用。

从那以后我每次给新机器配 Ext JS 环境,都强制按「装 Cmd、查版本、生成项目、立刻构建、开 watch、点一遍三个组件」这六步走一遍,一步不省。省掉的那一步,通常会在两周后的某个下午以白屏的形式回来找你。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进