zoukankan      html  css  js  c++  java
  • Sencha, the nightmare!

    基础

    创建一个应用程序

    sencha -sdk /path/to/sdk generate app %name% /path/to/app

    跑起来

    cd /path/to/app

    sencha app watch

    放心,出错了会出红字,自己退回命令行。

    开浏览器,默认地址是 http://localhost:1841

    在 watch 模式下,任何对源程序的修改都会自动更新,方便马上看到效果。看起来还挺方便,但是因为过度的 js 对象化包装,使得 Sencha 的应用调试起来无比困难。生产化打包编译以后,更是只有一个 app.js,万一出错了的话,你是找不到源头的了。

    目录结构

    主要注意下面几个文件夹

    app

    与具体平台、设备分辨率无关的东东。比如下面要提到的数据模型、Store。

    想法挺好,可是缺乏 IDE 支持的情况下(其自家的开发工具还不支持 6.0.2 版本的 Sencha),在各个目录之间跳转切换是非常麻烦的。即便用了 file buffer,你也得记住文件 id。

    classic

    经典 :) 听上去像极了 IIS Classic。就是传统的网页应用程序。写页面视图就在这里,也是默认的实现。

    modern

    现代,与经典对应。平板和触碰设备用。

    packages

    自定义的程序包,比如主题,就放在这里。默认的界面主题如果不能满足需要,那么就可以自定义主题。虽然自定义是非常痛苦的。

    resources

    图片,通用的文件放在这里。

    数据

    Model

    模型,或者叫数据模型,可以看作数据库存储的结构映射。

    定义一个数据模型,继承自 Ext.data.Model

    Ext.define("Inventory.model.Band",{
        extend:'Ext.data.Model',
        fields:[
            {name:'Id', type:'int'},
            {name:'Start', type:'float',allowBlank:false },
            {name:'End', type:'float',allowBlank:false},
            {name:'Wavelength', type:'string',allowBlank:false }
        ]
    });

    顺便说一句,用不同文件夹来存放同一个功能模块各个不同组件的做法非常落后。这本是用 IDE 和命名规范可以轻易解决的问题。而在类名里面加上文件夹的结构,则更是多余:多继承或者引用、实现抽象类的时候,多个文件夹结构你怎么放、怎么起名?

    Store

    存储。其实是存储代理的定义,即,从哪儿读取数据,又将数据写回哪儿。

    其 load 函数在数据读取完成后回调,可以对返回的数据做进一步处理,比较方便。需要绑定数据模型使用。

    proxy 属性指明了实际进行数据库(存取)操作的服务地址,这里也就出了 Sencha 的圈儿了,Spring 也可以、ASP.NET 也可以,随意。

    Ext.create('Ext.data.Store',{
        model:'Inventory.model.Band',
        id:'remotestore',
        proxy:{
            type : 'rest',
            url:'http://localhost:40544/Band.svc/GetBands',
            reader : {
                type : 'json',
                rootProperty : 'd'
            }
        },
        listeners:{
            load:function ( pageStore, records, successful , pageOperation , eOpts ){
                var bs = {bands:[]};
                 for(var i=0;i<records.length;i++){
                     bs.bands.push(records[i].data);
                 }
                Ext.getStore('bandstore').setData(bs);
            }
        }
    });

    ViewModel

    视图模型,即对页面上所放字段的映射。可以是数据模型的一部分,也可以是多个关联数据模型的组合。但其实 Sencha 这么搞,是把简单问题弄复杂了,因为 html 页面本身就有表单和字段,直接 parse 其键值对即可;而现在则必须再重新定义一遍这些字段,等于同样的定义在 html 表单和模型视图里面各自写了一遍,重复了。

    定义一个视图模型

    Ext.define('Inventory.view.main.MainModel', {
        extend: 'Ext.app.ViewModel',
        alias: 'viewmodel.main',
        data: {
            name: 'Inventory'
        }
    });

    使用的时候,首先在页面里面说明要用到的视图模型是哪个,然后对页面上可以 set 的属性绑定视图模型的字段,比如下面这个,绑定页面的标题:

    viewModel: 'main',
    header: {
        title: {
            bind: {
                text: '{name}'
            }
        }
    }

    视图

    放在页面上的可视区域,用来显示内容、提供交互操作。类似 SharePoint 上面的 WebPart。但是 WebPart 的本意是让用户也可以自定义页面(这个想法也是挺天真),视图则是让程序员来自定义页面(这个想法更是天真)。

    创建一个新视图,名字叫 band.Band,但是放在 main 文件夹里面。这就是我前面说的,文件夹归类法不靠谱的地方。

    Ext.define('Inventory.view.band.Band', {
        extend: 'Ext.panel.Panel',
        xtype: 'bandview',
        items :[
            {html:'<h2>hello!</h2>'}
        ]
    });

    我们也可以用之前定义的视图模型来动态地显示点儿内容:

    Ext.define('Inventory.view.band.Band', {
        extend: 'Ext.panel.Panel',
        xtype: 'bandview',
        viewModel: 'main',
        items :[
            {bind:{html:'<h2>hello,{name}!</h2>'}}
        ]
    });

    表单

    下面来一个复杂点儿的视图模型绑定,将 band 绑定到一个表单 form 上面:

    {
        xtype: 'form',
        defaultType: 'textfield',
        viewModel: 'band', //this viewModel will provide default values.
        margin: '5, 0, 20, 0',
        items:[
            { name: 'Id', fieldLabel: 'Id', readOnly: true, bind: { value: '{Id}'} },
            { name: 'Wavelength', fieldLabel: 'Wavelength', bind: { value: '{Wavelength}'} },
            { name: 'Start', fieldLabel: 'Start', bind: { value: '{Start}'} },
            { name: 'End', fieldLabel: 'End', bind: { value: '{End}'} },
            { name: 'Reset', text: 'Reset', xtype: 'button', handler: function() { var form = this.up('form').getForm(); form.reset(); } }
        ]
    }

    滚动条

    有的时候表单内容太多会超出窗口范围,此时可以用滚动条属性(又一个重复的发明):

    scrollable: true

    列表

    列表可以用 store 绑定,哪怕这个 store 是从内存里面读取的预定义的数据。

    Sencha 的文档里面对这种绑定描述甚少,值得批评。下面的例子,当选择一条记录的时候,自动将选中的值填充到前面的 form 里面。

    //a grid, using store to retreive data
    {
        xtype: 'grid',
        border: true,
         600,
        store: {type: 'bandstore' },
        columns: [
            { text: 'Id',  dataIndex: 'Id', 100 },
            { text: 'Wavelength',  dataIndex: 'Wavelength', 200 },
            { text: 'Start', dataIndex: 'Start', flex: 1, 100 },
            { text: 'End', dataIndex: 'End', flex: 1, 100 }
        ],
        listeners: {
            selectionchange: function(sm, selections){
                if(selections.length==0)return;
                var form = this.up('panel').down('form').getForm();
                form.setValues(selections[0].data);
            }
        }
    }

    当然,这不是列表和表单的常用方法,只是基础。后面 Jony 会提供更复杂的玩儿法。

    高级绑定

    比如,上面的那个 listeners 里面的 selectionchange 方法,其实是可以去掉的,只要这样写:

    Ext.define('Inventory.view.band.Band', {
        extend: 'Ext.panel.Panel',
        xtype: 'bandview',
        viewModel: 'main',
        items :[
            //a random message showing viewmodel binding
            { bind: { html: '<h2>hello,{name}!</h2>' } },
            //a form, with viewmodel binding as well
            {
                xtype: 'form',
                defaultType: 'textfield',
                margin: '5, 0, 20, 0',
                items:[
                    { name: 'Id', fieldLabel: 'Id', readOnly: true , bind: { value: '{bandgrid.selection.Id}'} },
                    { name: 'Wavelength', fieldLabel: 'Wavelength' },//, bind: { value: '{Wavelength}'} },
                    { name: 'Start', fieldLabel: 'Start' },//, bind: { value: '{Start}'} },
                    { name: 'End', fieldLabel: 'End' },//, bind: { value: '{End}'} },
                    { name: 'Reset', text: 'Reset', xtype: 'button', handler: function() { var form = this.up('form').getForm(); form.reset(); } }
                ]
            },
            //a grid, using store to retreive data
            {
                xtype: 'grid',
                reference: 'bandgrid',
                border: true,
                 600,
                store: {type: 'bandstore' },
                columns: [
                    { text: 'Id',  dataIndex: 'Id', 100 },
                    { text: 'Wavelength',  dataIndex: 'Wavelength', 200 },
                    { text: 'Start', dataIndex: 'Start', flex: 1, 100 },
                    { text: 'End', dataIndex: 'End', flex: 1, 100 }
                ]
            }
        ]
    });

    Sencha 的思想,是用编程的方式来粘合 Web 应用程序的组件,所以配置属性就能工作是最好的,Sencha 的框架自己知道如何找到关联数据并联系起来。

    嗯,想得挺好的。这么做有一个前提:有完整的设计,且几乎不会变更。

    调试

    如果不幸地,你的 Sencha 项目被集成进了某个服务器环境(比如 weblogic),那么,单独开一个并行的同类 Sencha 应用就变得非常有用了。

  • 相关阅读:
    python-进程池实例
    python-进程通过队列模拟数据的下载
    python-多进程模板
    python-多线程同步中创建互斥锁解决资源竞争的问题
    CentOS6.5配置网络
    解决CentOS系统Yum出现"Cannot find a valid baseurl for repo"问题
    CentOS 6.5安装图形界面
    Centos安装git
    Web前端优化,提高加载速度
    谁说写代码的不懂生活
  • 原文地址:https://www.cnblogs.com/jonyzhu/p/6003243.html
Copyright © 2011-2022 走看看