Ext JS 6和Sencha CMD 6的入门很简单。一个命令,即可生成一个功能完整的“通用”应用程序,可以运行在本地服务器上.
这个“通用”的应用程序包含一组核心的stores,模型(models)和控制器(controllers),过两个工具包:经典(Classic)和现代(Moden),展示不同的视图
经典(classic)工具包(toolkit)包含支持传统的浏览器,平板电脑和触摸屏笔记本电脑的 Ext JS 源码库。现代(modern)工具包(toolkit)包含一个对触摸支持比较好的源码库,支持现代浏览器,平板电脑和手机
让我们开始吧!
打开你的终端或控制台窗口并执行这些命令:
sencha -sdk /path/to/extjs/framework generate app AppName path/to/app cd /path/to/app sencha app watch
注意:在这个例子中,我们把App名称定为MyApp,path/to/app则是./MyApp.
就是这样. 您已经创建并部署了一个应用程序服务器,现在访问http://localhost:1841.你现在可以查看这个新生成的 Ext JS 6 应用程序了. 它应该是这样的:
Sencha Cmd 现在正在监控你应用程序的改动。你会看到 “Waiting for changes…”,这表明,你的应用程序是最新的. 当你修改并保存文件,你将看到打印了其他消息,但是这些很快就会出现另一个 “Waiting for changes…”. 这个周期通常需要几秒钟的时间,所以一定要在保存文件之后预留足够的时间,然后再刷新浏览器.
注意: 如果sencha app watch
因为某些原因导致没能监控到变更, 你只要简单地按下 CTRL + c 停止, 并重新启动 app watch.
注意: 如果你想了解上面的步骤具体包含什么内容, 请看Sencha Cmd 介绍.
下一步
像上面提到的, 通用(Universal)应用程序有三部分构成:
- 共享 app 部分 (通常是 stores, models, 和 controllers 最合适). 这部分位于应用程序根目录的
app
文件夹内. - Classic app 部分 (views 和 特定于应用程序 classic 方面的 ). 这部分位于应用程序目录下的
classic/src
文件夹内. - Modern app 部分 (views 和 特定于应用程序 modern 方面的). 这部分位于应用程序目录下的
modern/src
文件夹内.
应该注意的是,这个小应用程序演示了很多 Ext JS 的特性. 没有足够空间深入讨论所有内容, 所以我们将对这些相关的点做一个简要概述. 每个主题中, 我们会尽可能向你提供更深入的信息
我们先来看看 Main classic 视图 ,它位于 MyApp/classic/src/view/main/
.
Classic
Main classic 视图会在桌面浏览器或者平板设备上显示, 除非你指定了build targets.
用你最喜欢的 IDE 或文本编辑器, 打开 MyApp/classic/src/view/main/Main.js
. 这是我们这个 classic 应用程序的主要入口. 它也是容纳一个 tabpanel 和它的四个子 tab 页的容器. 另外, 你还可以看到第一个 tab 里面用到了我们的 表格(grid) 类.
让我们来看看各个 tab.
标签页(Tabs)
TabPanels 同样可用于标准面板(Panel)布局, 也可以容纳子组件(items). 这些子组件被 卡片(Card) 布局管理, 并呈现为一个个标签页的样式.
Tabs 通常横向配列在顶部. 不过, 在这个应用程序中, 我们聪明地改造了一下.
你应该注意到了我们的 tabs 不像一般的 tabs. 这是因为我们创建了一个自定义 UI.
UI 样式设计
Ext JS 框架中的每个组件都有一个 ui
配置,默认值是 default
. 这个属性可以修改,这样组件就都有了自己的与众不同的样式.
大部分 Ext JS 组件都有 SASS 混入函数(@mixin) , 你可以用它来快速生成新的 UI. 这些组件主要包括: Ext.panel.Panel, Ext.button.Button, Ext.Toolbar, Ext.window.Window, 等等.
我们来打开我们这个 tabpanel 的自定义 UI,看看里面有什么. tabpanel 的自定义 UI 的文件在这里:
`classic/sass/src/view/main/Main.scss`
正如你所看到的, 创建 UI 很简单. 只要调用组件相关的 混入函数(@mixin) 即可创建出 UI.
@include extjs-tab-panel-ui(
$ui: 'navigation'
);
混入函数(@mixin) 里的所有参数,你都可以修改.
然后你可以像这样在组件中使用 UI:
ui: 'navigation',
下面我们会详细讨论用 SASS 样式化你的应用程序.
响应式(自适应网页设计)
你可能注意到了,我们给 tabPanel 和 tabConfig
增加了 Responsive 插件.
// TabPanel
responsiveConfig: {
tall: {
headerPosition: 'top'
},
wide: {
headerPosition: 'left'
}
},
// Tab Config
tabConfig: {
plugins: 'responsive',
responsiveConfig: {
wide: {
iconAlign: 'left',
textAlign: 'left'
},
tall: {
iconAlign: 'top',
textAlign: 'center',
width: 120
}
}
}
这个插件,可以允许我们根据 viewport 的宽高来设定一套规则,用来改变 tabpanel 和 tab 按钮的文字和图标. 此时, 如果你调整浏览器窗口大小使得宽度小于高度,那么 tabpanel 的按钮 会移动到界面顶部,tab 按钮的文字和图标也会改变位置.
如果 viewport 宽度大于高度, tab 按钮就会出现在左边,并相应调整按钮的文字和图标.
你可以点击这里,阅读更多有关 responsive 插件类和为多屏幕多环境开发的内容.
你可能注意到了,第2、3、4个标签页的内容并不是写死的. 这是因为我们是从一个 ViewModel 里绑定的数据.
视图模型(View Models)和数据绑定
视图模型(View Models) 和 数据绑定
允许你用声明的风格,写很少的代码,却做更多的事情.
视图模型(View Model) 是一个管理数据对象的类. 需要这些数据的组件可以绑定到 View Model, 而且可以在数据发生变化的时候通知组件更新界面. 视图模型(View Model) 和 视图控制器(ViewController)类似, 只被引用了它的 view 所拥有.
在大多数情况下, 任何具有 setter 访问器的 配置项(config), 都可以绑定到 ViewModel 的数据上. 这个例子中, 我们用的是setHtml()
和 setTitle()
.
我们来看看下面的代码:
// View Model 声明
viewModel: 'main',
// 绑定到标题栏的 title
header: {
title: {
bind: {
text: '{name}'
},
flex: 0
}
},
// 绑定到标签页的 HTML 配置上
{
title: 'Users',
iconCls: 'fa-user',
bind: {
html: '{loremIpsum}'
}
}
可以看到数据从 ViewModel (app/view/main/MainModel.js
) 绑定到了 标签页(tabs) 和 应用程序的标题(title). ViewModel 的数据是今天的, 不过大多数情况下数据是通过 代理(proxy) 生成的.
可以查看视图模型(View Models) 和数据绑定指南获得更多内容.
表格(Grids)
接下来, 我们打开MyApp/classic/src/view/main/List.js
看看 Ext.grid.Panel .
List.js 内有一个表格(grid), 位于Main tabpanel 的第一个标签页(tab)内. 用了很少的代码,我们就创建出了一个功能很全的 grid. 默认地, 每一个 列(column)都可以通过点击列头来在 升序(ASC) 和 降序(DESC) 之间切换排序. 每个列头默认也是可以重排序的, 并且每一个列都有一个下拉菜单,菜单里有选项可以隐藏或显示表格列.
不仅如此, 独立配置每一列也很简单.
我们稍后仔细分析一些 grid 的 配置:
Store
可以看到, 我们给store 里添加了一些人的信息. 如果你仔细看, 你会发现在 classic 区域下并没有 store 类的定义. 这是因为这个 store 是定义在通用(universal)区域下的, app/store/Personnel.js
. 我们放在这里是可以让 Classic grid 和 Modern grid 可以共享同一个 store 和数据.
在实际开发中, 上面的 store 应该会有一个 proxy, proxy 设有一个 url 属性, 这样就可以从服务端拉取数据. 为了形象化描述, 在这个例子里,我们只在 store 里面写了些内置数据. 不过大多数情况是很少用内置静态数据的.
事件监听(Listeners)
你会发现 Listeners 对象包含了一个调用‘onItemSelected’函数的select
事件. 同样的, 在 classic 区域下你也找不到带有此逻辑的 view controller. 你可以在通用(universal)区域下找到 MainController.js
, 因为 Modern 和 Classic 的 grid 共享这个 select
事件的监听函数.
如果你没发现, 那我们打开 app/view/main/MainController.js
看看.
你会看到一些很简单的逻辑:
onItemSelected: function (sender, record) {
Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
},
在 Classic 和 Modern 的 grid (待会介绍)中, 我们监听了 select
事件. 控制器的逻辑一致地处理了这2个组件的 select
事件.
我们下面会讨论更多关于 通用(universal)控制器(controllers) 的内容.
讲到这里, 我们已经涵盖了大部分 Classic 里面的东西. 然后我们来看看 Modern toolkit 里面的东西.
Modern
和 Classic 一样, 我们先看下 MyApp/modern/src/view/main/Main.js
.
这是 Modern 应用程序的主要入口. 以同样的方式, 你可以发现 Main 是一个容器,容纳了一个 tabPanel 和它的4个标签页. 此外, 第一个标签页包含了一个 Modern 表格(Grid).
标签页(Tabs)
Modern toolkit 的 tabpanel 是用来全屏切换显示多个 view 的一个很好方式. TabPanel 里的每一个子组件都对应一个 Tab 按钮, 点击它就显示相应子组件. Tabs 可以位于 TabPanel 的顶部也可以位于底部.
你可以看到这个 Modern 视图(view) 和 Classic 的 view 有很多相似的地方. 例如:
- 共享 ViewController
- 共享 ViewModel
- 与绑定有关的配置(Bound Configs)
Modern 表格(Grid)
Modern Toolkit 内置一个轻量级的表格(grid), 它为触摸设备而优化, 可以很方便的在触摸设备上获取, 排序, 过滤, 和编辑大量数据. 它也很容易配置和自定义列的数据展示(渲染).
和 Classic Toolkit 的 grid 类似, 可以看到一个共享的通用(universal) store ,还有一个监听了 select
事件的 listeners 对象.
通用(Universal)
我们已经接触了我们应用程序通用区域的所有代码. 也就是说, 你需要很仔细地利用这个区域. 此时, 你应该避免把应用程序视图(Views)放到这里面. 如果你 require 或引用了一个不存在于某个 toolkit 的类, build 应用程序时就会遇到错误.
这个区域应该留给2种 toolkits公共的核心部分.
- ViewControllers
- ViewModels
- Models
- Stores
未来, 我们会继续在组件通用方向上努力,以便可以减少对共享 view 的顾虑.
最后, 在这2个 toolkit 中, 你要确保你要用的任何事件都具有相同的参数, 而且是被同样的意图触发的.
改变主题
现在我们来关注一下应用程序的外观. 除非指定了主题, 每个新创建的应用程序都用的是默认主题 (Triton). 也就是说, 对于一个以创建的应用程序,更换主题是非常简单的.
我们来试试 Ext JS Crisp 主题.
你要做的就是打开应用程序里的 app.json 文件,修改 theme
属性:
"theme": "theme-neptune"
为:
"theme": "theme-crisp"
等 app watch 结束之后, 刷新页面,你应该可以看到你的应用程序样子已经改变了.
改变应用程序的样式
在大多数场合, 你需要自定义应用程序的外观. 看起来不错,就是蓝色不太合适. 我们来尝试把 tabpanel 标题栏的颜色修改成更有特点一些.
注意: 下面的操作会改变你应用程序中 classic 视图的样式. 未来, Ext JS 6 会改进以便支持可以改变2种 toolkit 的视图的样式.
通过创建和修改 SCSS 文件,你可以很简单、高效的改变应用程序的样式.
SCSS (Sassy CSS) 是 SASS 的语法, 支持嵌套样式规则、支持变量和混入函数(mixins). 然后再处理并转换为传统的 CSS 文件,以便在浏览器使用.
所有全局 SCSS 变量的列表, 可以查看我们的API文档: Global_CSS
各个组件也有一些特定的 SCSS 变量可供使用. 比如, 你可以在 Panel 的 API 文档页的“CSS Variables”部分找到关于 Panel 的 SCSS 变量: Ext.panel.Panel
如果你打开classic/sass/src/view/main/
文件夹, 你会看到一个名为Main.scss
的文件. 这些文件夹和文件可以根据需要动态手动添加. 对于应用程序中的每一个类, Sencha Cmd 会自动查找对应的 SCSS 文件,从sass/var/
查找变量, 从 sass/src/
查找样式规则.
添加这些文件后会自动被 sencha app watch
检测到.
再来看看 Main.scss
文件.
正如你所看到的, 我们为 main 视图定义了一些 SCSS 规则. 顶部的 panel 的样式由下面的代码设置:
$ui-header-background-color: $base-color,
在你的颜色变化范围内,你有几个选择. 如果你只希望这一块不是蓝色,你可以明确地把它设置为一个特定的颜色,如:
$ui-header-background-color: #87BD3E,
当 sencha app watch
检测到变更并处理完之后, 刷新页面, 可以看到 tabpanel 标题栏的颜色现在是绿色了 (#87BD3E).
不过, 如果你想全局替换整个应用程序的蓝色为绿色, 你可以修改 $base-color
的值. 你需要创建一个 SCSS 文件,用来存放全局规则:
classic/sass/etc/all.scss // all.scss 可能包含任意 SASS / CSS 规则
创建了文件之后, 你可以新增一个$base-color
声明,覆盖掉应用程序主题中的 $base-color
值. 此处, 我们用之前的绿色.
$base-color: #87BD3E !dynamic;
应用程序刷新之后, 你应该看到很多组件现在都是绿色了.
总结
现在你知道使用 Ext JS 和 Sencha Cmd 来创建并运行一个应用程序是多么简单了吧. 记得一定要查看我们这个例子中用到的所有组件和类的 API 文档.