美文网首页js我爱编程
Sencha Cmd创建Ext JS示例项目

Sencha Cmd创建Ext JS示例项目

作者: 写意悠悠 | 来源:发表于2016-06-01 15:29 被阅读0次

    Sencha提供了免费的Cmd工具,可以用来创建Ext JS项目并提供了一些便利的功能。
    Sencha也在官方文档中提供了一个示例来演示如何创建一个Sample Login App。
    本文就介绍一下这个官网示例。

    准备工作
    • 下载Sencha Ext JS的SDK,本文中使用的是开源的GPL的6.0.1版本
    • 下载Sencha Cmd,这个是免费的,本文中使用的是Windows 64-bit带JRE的6.1.2版本

    一些废话:
    也许Sencha是为了更好地推它的商用版本吧,从6.0.0版本开始,就把GPL版本的下载位置藏的很深,而且还需要通过发送邮件的方式来提供下载。

    安装
    • SDK解压缩放到一个指定目录,本文中为D:\ext-6.0.1
    • Cmd安装到默认位置即可

    一些废话:
    6.x版本从以前方便很多,如果你使用的是5.x版本,那还需要额外安装JDK, ANT, Ruby, SASS, COMPASS,这里就不啰嗦了。

    本文创建的示例项目的路径为D:\TutorialApp


    那我们开始创建程序吧。
    打开cmd命令行,使用sencha [-sdk SDK所在目录] generate app [-classic|-modern] AppName App目录命令来创建项目。

    sencha -sdk D:\ext-6.0.1 generate app -classic TutorialApp D:\TutorialApp
    
    • -sdk D:\ext-6.0.1指明Ext JS SDK的所在目录,如果运行命令行的所在目录就是SDK目录(D:\ext-6.0.1),则可以省略
    • -classic|-modern可以省略,Ext JS的6.0版本其中一个主要的更新就是把Ext JS和Touch合并,在创建时可以选择哪一种类型,classic对应Ext JS,而modern对应Touch。如果省略,则创建所谓的universal类型,即classic和modern并存。在本文中演示的是桌面端程序,所以我们选择classic。
    • TutorialApp是项目名称,也将作为该项目的namespace。
    • D:\TutorialApp是项目名录

    一些废话:
    运行命令后,可以去倒一杯水,起来活动活动,因为这个过程大概会持续几分钟。完成之后,看下TutorialApp目录的大小,会发现大概500M,真够大的。

    从命令进入项目目录D:\TutorialApp,并输入命令sencha app watch

    cd D:\TutorialApp
    sencha app watch
    

    一些废话:
    运行命令后,可以再起来活动活动。

    sencha app watch会启动内置的jetty服务器,可以使我们方便地通过http://localhost:1841/ 来查看页面。而且watch会监听项目目录中的文件变化而自动build。

    这时候打开http://localhost:1841/ 会看到Cmd自动创建的默认首页长这样子。6.x版新增加的Triton主题和以前的主题有明显的不同。

    打开D:\TutorialApp目录,看下Cmd自动创建的目录和文件:

    .sencha/                        # 里面存放的大多都是配置相关的文件,一般不需要修改
    ext/                            # Ext JS SDK的一份copy,所以才会这么大
    index.html                      # 首页
    app.json                        # 项目主配置文件
    app.js                          # 项目主程序
    app/                            # 项目源码目录
        model/                      # Model目录
        store/                      # Store目录
        view/                       # View目录
            main/                   # 首页的目录
                Main.js             # 首页的View
                MainModel.js        # 首页的ViewModel
                MainController.js   # 首页的ViewController
        Application.js              # Ext.Application
    packages/                       # Sencha Cmd packages
    workspace.json                  # Workspace的描述文件
    build/                          # 保存项目最终的build结果
    

    还有一些目录和文件没有列举出来,那些目录和文件一般都不需要我们去修改,前期可以忽略。
    对我们来说,最重要的目录就是app目录,这是项目的源码目录,我们写的代码都保存在里面。
    app目录下包含三个子目录:

    • model: 保存Model对象,Cmd也提供了命令来创建Ext JS中的Model对象。比如User,它包含id,name,email三个字段。在命令行中运行:
    cd D:\TutorialApp
    sencha generate model user.User id:int,name,email
    

    运行Cmd的命令需要先进入项目目录,运行之后会看到model目录里多了一个子目录user,user目录里有新建的User.js文件。

    app/                          # 项目源码目录
        model/                      # Model目录
            user/                   # user子目录
                User.js             # User.js定义了User的字段
    

    关于Ext JS的Model的具体用法,请参照官方API文档:Ext.data.Model

    • store: Ext JS的Store可以理解为Model对应的数据集合,在Store中可以定义怎么去读取Model。具体用法,请参照官方API文档:Ext.data.Store
    • view:所有和UI相关的代码都保存在这里,比如窗口,表格,图表等。可以为每个UI创建对应的ViewController(Ext.app.ViewController)和ViewModel(Ext.app.ViewModel)。

    由于这个示例程序要演示的是创建一个登录窗口,只有等登录完成之后才会显示首页。所以首先要打开项目根目录下的app.js,将和TutorialApp.view.main.Main相关的代码删除。修改后的app.js长这样:

    Ext.application({
        name: 'TutorialApp',
        extend: 'TutorialApp.Application
    });
    

    如果你仍然保持sencha app watch的运行状态,则Cmd会检测到你对app.js的修改。此时访问首页,就会看到一片空白。

    接着来创建用户的登录窗口,它是长这样子的:

    可以在app\view目录里手动创建login子目录,并在login目录下手动创建Login.js和LoginController.js。也可以在命令行中运行以下命令来让Cmd自动创建:

    cd D:\TutorialApp
    sencha generate view -base Ext.window.Window login.Login
    

    -base参数用来设置创建的UI是哪种类型,由于我们要创建的是窗口,所以继承的是Ext.window.Window。

    Login.js是登录窗口的代码,最后长这样:

    Ext.define('TutorialApp.view.login.Login', {
        extend: 'Ext.window.Window',
        xtype: 'login',
    
        //Login窗口会包含一个表单(Ext.form.Panel)
        //LoginController里定义了Login窗口会使用到的方法onLoginClick
        //requires可以确保这2个类会在Login初始化完成之前先被初始化
        requires: [
            'TutorialApp.view.login.LoginController',
            'Ext.form.Panel'
        ],
        //绑定controller,绑定时使用的是别名
        controller: 'login',
        //padding: 10px
        bodyPadding: 10,
        //窗口的标题栏文字
        title: 'Login Window',
        //隐藏窗口右上角的关闭按钮"x"
        closable: false,
        //Window的autoShow默认为false
        //Window可以用show()和hide()来手动显示和隐藏
        //把autoShow设为true, 则在Window创建之后会自动显示
        autoShow: true,
        //把窗口里的UI组件放在items里
        items: {
            //表单
            xtype: 'form',
            reference: 'form',
            //把表单里的UI组件放在表单的items里
            items: [{
                //供用户输入用户名的文本框
                xtype: 'textfield',
                name: 'username',
                //fieldLabel是显示在文本框前的标签文字
                fieldLabel: 'Username',
                //打开非空校验,即要求输入的用户名不能为空
                allowBlank: false
            }, {
                //供用户输入密码的文本框
                xtype: 'textfield',
                name: 'password',
                //inputType设为password,则用户输入的内容会以*回显在屏幕上
                inputType: 'password',
                fieldLabel: 'Password',
                allowBlank: false
            }, {
                //显示在密码输入框下方的文字
                xtype: 'displayfield',
                hideEmptyLabel: false,
                value: 'Enter any non-blank password'
            }],
            //表单的按钮
            buttons: [{
                //按钮上的显示文字
                text: 'Login',
                //设为true,则Login按钮在表单通过校验前是不能被点击的
                formBind: true,
                listeners: {
                    //当按钮被点击时
                    click: 'onLoginClick'
                }
            }]
        }
    });
    

    LoginController.js是Login的Controller,最后长这样:

    Ext.define('TutorialApp.view.login.LoginController', {
        extend: 'Ext.app.ViewController',
        //定义别名为login
        alias: 'controller.login',
        //当Login按钮被点击时
        onLoginClick: function() {
    
            //这本例中使用localStorage来保存用户的登录状态
            //这里省略了用户信息的远程校验过程
            //只要用户输入用户名和密码,点击Login按钮即认为用户成功登陆
            localStorage.setItem("TutorialLoggedIn", true);
            //getView()返回的是controller绑定的view, 在本例中就是Login窗口
            //登录后不再需要Login窗口,所以调用destroy()来删除
            this.getView().destroy();
            //关闭Login窗口后,需要显示首页
            //使用Ext.create()来创建view\main\Main.js
            Ext.create({
                xtype: 'app-main'
            });
    
        }
    });
    

    登录窗口写好了,但还不会显示,需要修改app\Application.js。
    Application.js最后长这样:

    Ext.define('TutorialApp.Application', {
        extend: 'Ext.app.Application',
        
        name: 'TutorialApp',
    
        stores: [
            // TODO: add global / shared stores here
        ],
    
        views: [
            'TutorialApp.view.login.Login',
            'TutorialApp.view.main.Main'
        ],
        
        launch: function () {
            var loggedIn;
            //从localStorage读取用户登录状态
            loggedIn = localStorage.getItem("TutorialLoggedIn");
            //如果用户已登录,则显示首页,否则显示Login窗口
            Ext.create({
                xtype: loggedIn ? 'app-main' : 'login'
            });
        },
    
        onAppUpdate: function () {
            Ext.Msg.confirm('Application Update', 'This application has an update, reload?',
                function (choice) {
                    if (choice === 'yes') {
                        window.location.reload();
                    }
                }
            );
        }
    });
    

    最后在首页上加上一个Logout按钮,修改后的app\main\Main.js长这样:

    Ext.define('TutorialApp.view.main.Main', {
        extend: 'Ext.tab.Panel',
        xtype: 'app-main',
    
        requires: [
            'Ext.plugin.Viewport',
            'Ext.window.MessageBox',
    
            'TutorialApp.view.main.MainController',
            'TutorialApp.view.main.MainModel',
            'TutorialApp.view.main.List'
        ],
    
        controller: 'main',
        viewModel: 'main',
        plugins: 'viewport',
    
        ui: 'navigation',
    
        tabBarHeaderPosition: 1,
        titleRotation: 0,
        tabRotation: 0,
    
        header: {
            layout: {
                align: 'stretchmax'
            },
            title: {
                bind: {
                    text: '{name}'
                },
                flex: 0
            },
            iconCls: 'fa-th-list',
            //添加Logout按钮
            items: [{
                xtype: 'button',
                text: 'Logout',
                margin: '10 0',
                handler: 'onClickButton'
            }]
        },
    
        tabBar: {
            flex: 1,
            layout: {
                align: 'stretch',
                overflowHandler: 'none'
            }
        },
    
        responsiveConfig: {
            tall: {
                headerPosition: 'top'
            },
            wide: {
                headerPosition: 'left'
            }
        },
    
        defaults: {
            bodyPadding: 20,
            tabConfig: {
                plugins: 'responsive',
                responsiveConfig: {
                    wide: {
                        iconAlign: 'left',
                        textAlign: 'left'
                    },
                    tall: {
                        iconAlign: 'top',
                        textAlign: 'center',
                        width: 120
                    }
                }
            }
        },
    
        items: [{
            title: 'Home',
            iconCls: 'fa-home',
            items: [{
                xtype: 'mainlist'
            }]
        }, {
            title: 'Users',
            iconCls: 'fa-user',
            bind: {
                html: '{loremIpsum}'
            }
        }, {
            title: 'Groups',
            iconCls: 'fa-users',
            bind: {
                html: '{loremIpsum}'
            }
        }, {
            title: 'Settings',
            iconCls: 'fa-cog',
            bind: {
                html: '{loremIpsum}'
            }
        }]
    });
    

    在首页的对应的Controller,app\main\MainController.js中添加Logout对应的click方法

    Ext.define('TutorialApp.view.main.MainController', {
        extend: 'Ext.app.ViewController',
    
        alias: 'controller.main',
    
        onItemSelected: function (sender, record) {
            Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
        },
    
        onConfirm: function (choice) {
            if (choice === 'yes') {
                //
            }
        },
        //点击Logout按钮
        onClickButton: function () {
            //删除保存在localStorage中的登录状态
            localStorage.removeItem('TutorialLoggedIn');
            //删除首页
            this.getView().destroy();
            //创建Login窗口
            Ext.create({
                xtype: 'login'
            });
        }
    });
    

    写代码到此就完成了,运行sencha app build命令

    cd D:\TutorialApp
    sencha app build
    

    运行结束后,在build目录下会生成production子目录,可以把该目录下的TutorialApp目录发布到其他服务器上,比如Apache HTTP Server的htdocs目录里。

    相关文章

      网友评论

        本文标题:Sencha Cmd创建Ext JS示例项目

        本文链接:https://www.haomeiwen.com/subject/ptmcdttx.html