第一步 使用sencha touch cmd 4.0 创建项目、打包(加入全局变量、公用类、自定义扩展、资源文件)
参考资料:
http://www.cnblogs.com/qqloving/archive/2013/04/25/3043606.html
http://www.admin10000.com/document/140.html
这里我主要讲的是如何加入全局变量、公用类、自定义扩展、资源文件
官网地址:http://www.sencha.com/products/touch/
官当最新doc:http://docs.sencha.com/touch/
1.环境搭建
a.安装java
先下载JAVA,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html
安装到指定路径,例如F:\Java
打开计算机属性——高级系统设置——环境变量(如上文)
配置环境变量
变量: JAVA_HOME 值: 安装路径:F:\Java\jdk1.6.0_10
变量: Path 添加值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
变量: CLASSPATH 添加值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
JAVA配置完成,接下来验证配置是否成功。
击运行——输入cmd——回车——输入javac——回车,,如果出现一堆英文,如下图所示,即表示配置成功。
b.安装cmd
再下载 sencha touch 的sdk (一个js压缩包),现在最新的版本为2.3,我用的2.2.1版本
下载地址:http://www.sencha.com/products/touch/download/
然后下载 sencha touch cmd,一个工具,主要用来创建项目、生成测试包、部署包等,我用的4.0版本
下载地址:http://www.sencha.com/products/sencha-cmd/download/
c.安装ruby
用 sencha touch cmd 生成测试包或部署包时调用的命令需要ruby,主要用来做js和css压缩
下载地址:http://rubyinstaller.org/ (ps:需要下载1.93的版本,不要下载2.0的版本)
安装过程出现如下界面。如图
有3个选项分别是:(1) 是否安装tclTk支持。(2) 添加ruby命令路径到系统环境变量PATH。(3)是否将 .rb 和.rbw 文件关联到Ruby。
这里选择第二项即可
安装之后 测试cmd 是否安装成功
运行-》cmd ;输入sencha,看到下面的就说明cmd安装好了
检测当前cmd版本
sencha upgrade --check
更新cmd
sencha upgrade
如果你想升级到测试版
sencha upgrade --check --beta
sencha upgrade --beta
2.创建项目:
在cmd中输入以下命令
sencha -sdk D:\ASPX\touch-2.2.1 generate app app D:\ASPX\Test
D:\ASPX\touch-2.2.1:你选择的sdk根目录
app D:\ASPX\Test:在指定目录创建一个项目,命名空间为app
在谷歌浏览器中可以直接运行,不必搭建服务器。
如果开发过程中涉及到跨域问题,可以如下处理
找到谷歌浏览器,为其创建一个快捷方式,加入以下命令。--disable-web-security
关闭所有已经打开的谷歌浏览器,然后用你创建的快捷方式再次打开
把项目中index.html文件拖入即可。
3.加入全局变量以及公用类js
这是一个简略的开发环境
如图在app文件夹中加入config.js(全局变量),util.js(公用类)
他们的代码分别如下
1 /* 2 *所有配置信息 3 */ 4 Ext.define('app.config', { 5 alternateClassName: 'config', //设置别名是为了方便调用,这样直接config.weather就能获取到变量。 6 statics: { 7 //天气预报接口 8 weather: 'http://www.weather.com.cn/data/cityinfo/101210904.html', 9 //博客园 10 Cnblogs: 'http://www.cnblogs.com/mlzs/rss' 11 } 12 });
1 /*公共类*/ 2 Ext.define('app.util', { 3 alternateClassName: 'util', 4 statics: { 5 //加载stroe 6 storeLoad: function(id) { 7 var store = Ext.getStore(id); 8 if (store.getCount() < 1) { 9 store.load(); 10 } 11 }, 12 //Viewport添加新项,Viewport之中始终只有一项 13 ePush: function(xtype) { 14 var me = Ext.Viewport, 15 view = me.getActiveItem(); 16 if (view && view.getItemId() == xtype) { 17 return; 18 } 19 view = Ext.create(xtype, { 20 itemId: xtype 21 }); 22 //切换 23 me.animateActiveItem(view, { 24 type: 'slide', 25 direction: 'left' 26 }); 27 }, 28 //监控Viewport界面切换,切换时销毁旧项 29 eActiveitemchange: function() { 30 var me = Ext.Viewport; 31 me.onAfter('activeitemchange', 32 function(t, value, oldValue, eOpts) { 33 if (oldValue) { 34 //强制销毁,防止销毁不完全引发错误 35 me.remove(oldValue, true); 36 } 37 }); 38 }, 39 /*为Ext.Viewport添加一个消息提示组件*/ 40 addMessage: function() { 41 Ext.Viewport.setMasked({ 42 xtype: 'loadmask', 43 cls: 'message', 44 transparent: true, 45 indicator: false 46 }); 47 this.hideMessage(); 48 }, 49 /*显示一个消息提示*/ 50 showMessage: function(mes, autoHide) { 51 var me = this, 52 message = this.getMessage(); 53 message.setMessage(mes); 54 message.show(); 55 //是否自动关闭提示 56 if (autoHide) { 57 setTimeout(function() { 58 message.hide(); 59 }, 60 500); 61 } 62 }, 63 /*隐藏消息提示*/ 64 hideMessage: function() { 65 this.getMessage().hide(); 66 }, 67 //消息组件 68 getMessage: function() { 69 return Ext.Viewport.getMasked(); 70 }, 71 //重写ajax 72 overrideAjax: function() { 73 var me = this; 74 //开始加载 75 Ext.Ajax.on('beforerequest', 76 function(connection, options) { 77 if (!options.hidMessage) { 78 me.showMessage('正在努力加载中...'); 79 } 80 }); 81 //加载成功 82 Ext.Ajax.on('requestcomplete', 83 function(connection, options) { 84 me.hideMessage(); 85 }); 86 //加载失败 87 Ext.Ajax.on('requestexception', 88 function(connection, options) { 89 if (!options.hidMessage) { 90 me.showMessage('加载失败,请稍后再试...', true); 91 } 92 }); 93 }, 94 //重写list 95 overrideList: function() { 96 //重写分页插件 97 Ext.define("Ext.zh.plugin.ListPaging", { 98 override: "Ext.plugin.ListPaging", 99 config: { 100 //自动加载 101 autoPaging: true, 102 //滚动到最底部时是否自动加载下一页数据 103 noMoreRecordsText: '没有更多内容了', 104 loadMoreText: '加载更多...' //加载更多按钮显示内容 105 } 106 }); 107 //重写List 108 Ext.define("Ext.zh.List", { 109 override: "Ext.List", 110 config: { 111 //取消选择效果 112 selectedCls: '', 113 //禁用加载遮罩,防止跳转时页面卡顿,使用统一的遮罩效果 114 loadingText: false, 115 emptyText: '没有更多内容了' 116 } 117 }); 118 }, 119 //app初始化执行 120 inIt: function() { 121 this.eActiveitemchange(); 122 this.overrideList(); 123 this.overrideAjax(); 124 this.addMessage(); 125 } 126 } 127 });
直接utli.inIt();
config.weather就可以直接使用
创建一个ux文件夹,里面放置扩展插件。例如:
1 /* 2 *模仿tabpanel导航栏 3 */ 4 Ext.define('ux.TabBar', { 5 alternateClassName: 'tabBar', 6 extend: 'Ext.Toolbar', 7 xtype: 'tabBar', 8 config: { 9 docked: 'bottom', 10 cls: 'navToolbar', 11 layout: { 12 align: 'stretch' 13 }, 14 defaults: { 15 flex: 1 16 }, 17 //被选中的按钮 18 selectButton: null 19 }, 20 initialize: function () { 21 var me = this; 22 me.callParent(); 23 //监听按钮点击事件 24 me.on({ 25 delegate: '> button', 26 scope: me, 27 tap: 'onButtonTap' 28 }); 29 }, 30 //更新被选中按钮 31 updateSelectButton: function (newItem, oldItem) { 32 if (oldItem) { 33 oldItem.removeCls('x-tabBar-pressing'); 34 } 35 if (newItem) { 36 newItem.addCls('x-tabBar-pressing'); 37 } 38 }, 39 //当按钮被点击时 40 onButtonTap: function (button) { 41 if (!button.getInitialConfig('noSelect')) { 42 this.setSelectButton(button); 43 } 44 }, 45 /** 46 * @private 47 *执行添加项,调用add方法后自动执行 48 */ 49 onItemAdd: function (item, index) { 50 if (!this.getSelectButton() && item.getInitialConfig('selected')) { 51 this.setSelectButton(item); 52 } 53 this.callParent(arguments); 54 } 55 });
在app.js中需要加入
1 //指定ux起调目录 2 Ext.Loader.setPath({ 3 'ux': 'app/ux' 4 }); 5 //简略写法 6 Ext.application({ 7 name: 'app', 8 appFolder: 'app', 9 controllers: ['Main', 'Panel', 'Layout', 'List'], 10 requires: ['app.config', 'app.util'], 11 launch: function () { 12 util.inIt(); 13 } 14 });
这样就可以通过ux.TabBar来使用自定义控件了
例如:
1 Ext.define('app.view.MyBar', { 2 alternateClassName: 'myBar', 3 extend: 'ux.TabBar', 4 xtype: 'myBar', 5 requires: ['app.view.About'], 6 config: { 7 items: [ 8 { 9 xtype: 'button', 10 text: '首页', 11 //只有第一个设置的属性有效 12 selected: true, 13 action: 'redirect', 14 redirect: 'home' 15 }, 16 { 17 xtype: 'button', 18 text: '关于', 19 action: 'redirect', 20 redirect: 'about' 21 }, 22 { 23 xtype: 'button', 24 text: '其他', 25 //没有选中效果 26 noSelect:true, 27 action: 'other' 28 }] 29 } 30 });
下面是资源文件的引入
在app.json文件中:
通过resources来配置资源文件,这样使用cmd打包时才会将资源文件复制到生成的项目中
下面是我的app.json,其中有我对各个配置的理解
1 { 2 /** 3 * 项目的命名空间 4 */ 5 "name": "app", 6 /** 7 * 项目起始html文件,路径相对于此app.json文件 8 */ 9 "indexHtmlPath": "index.html", 10 /** 11 * 运行此项目的url路径,比如: "http://localhost/myapp/index.html". 12 * 13 *当设置此值时,将不能通过文件系统直接访问。 14 */ 15 "url": null, 16 /** 17 * 所需引用js文件 18 * 单个格式如下 19 * { 20 * "path": "path/to/script.js" // 文件路径,如果本地文件,路径相对于此app.json文件 21 * "remote": true // (可选值) 22 * // -默认值为"false" 23 * // -"true",如果这个文件是一个远程文件不会被复制 24 * "update": "delta" // (可选值) 25 * // 如果没有指定,这个文件将只加载一次, 26 * // 缓存到localStorage里面,直到这个值被改变。 27 * // - "delta" 增量更新此文件 28 * // - "full" 当文件改变时,完全更新此文件 29 * "x-bootstrap": true // (可选值) 30 * // 表示这是项目依赖文件。 31 * // 该文件不会被复制到生成目录或引用 32 * 33 * } 34 */ 35 "js": [{ 36 "path": "touch/sencha-touch.js", 37 "x-bootstrap": true 38 }, 39 { 40 "path": "app.js", 41 /* 表示所有的类生成到这个文件 */ 42 "bundle": true, 43 "update": "delta" 44 }], 45 /** 46 *所需引用js文件 47 * 单个格式如下 48 * { 49 * "path": "path/to/script.js" // 文件路径,如果本地文件,路径相对于此app.json文件 50 * "remote": true // (可选值) 51 * // -默认值为"false" 52 * // -"true",如果这个文件是一个远程文件不会被复制 53 * "update": "delta" // (可选值) 54 * // 如果没有指定,这个文件将只加载一次, 55 * // 缓存到localStorage里面,直到这个文件被改变。 56 * // - "delta" 增量更新此文件 57 * // - "full" 当文件改变时,完全更新此文件 58 * 59 * } 60 */ 61 "css": [{ 62 "path": "resources/css/app.css", 63 "update": "delta" 64 }, 65 { 66 "path": "resources/css/main.css", 67 "update": "delta" 68 }], 69 /** 70 *项目生成时用于自动生成HTML5应用程序缓存清单(cache.manifest) 71 */ 72 "appCache": { 73 /** 74 * 本地缓存名单 75 */ 76 "cache": ["index.html"], 77 /** 78 * 网络缓存名单 79 */ 80 "network": ["*"], 81 /** 82 * FALLBACK缓存名单 83 */ 84 "fallback": [] 85 }, 86 /** 87 * 项目生成时需要复制的资源文件 88 */ 89 "resources": ["resources/images", "resources/icons", "resources/startup"], 90 /** 91 * 项目生成时忽略的文件/目录名称匹配,必须是有效的正则表达式 92 */ 93 "ignore": ["\.svn$"], 94 /** 95 * 之前生成项目储存目录,用于进行增量更新,不可随意改变此目录下的文件 96 */ 97 "archivePath": "archive", 98 /** 99 * 在cmd创建时需要引用的类 100 */ 101 "requires": [], 102 /** 103 * 唯一ID,作为localStorage前缀。 104 * 通常情况下,你不应该改变这个值。 105 */ 106 "id": "d8504e05-a9fc-4692-bdbc-94c3190751f5" 107 }
4.通过cmd生成项目
运行命令行工具,进入你的项目目录
运行cmd生成命令:
sencha app build native:直接打包成本地苹果或者安卓应用,具体参见http://www.cnblogs.com/mlzs/p/3470224.html
sencha app build production:生成web包,主要用于发布web版本
sencha app build package:生成压缩包
sencha app build testing:生成测试包
生成过程中,有错误请根据提示进行排错
如上生成成功
示例demo可以看这里:http://www.cnblogs.com/mlzs/p/3382229.html
此项目为了开发方便对结构进行了简化,使用cmd生成一个命名空间为app的项目,将demo项目中的文件复制到对应app项目目录中,使用cmd打包成功(已测)
项目build目录下可以找到生成之后的项目
类似下图: