组建和架构的包括固定的写法,风格还有规范,通过一个栗子(仅包含一个grid和点击事件),来描述extjs下的mvc和mvvm的整体结果

组建化

<!DOCTYPE HTML>
<html manifest="">

<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="UTF-8">
    <title>htjy</title>
    <link type="text/css" rel="stylesheet" href="css/font-awesome.css">
    <!-- The line below must be kept intact for Sencha Cmd to build your application -->
    <script type="text/javascript" src="/ext/build/ext.js"></script>
    <script type="text/javascript" src="/ext/build/ext-all.js"></script>
    <script src="/ext/packages/ext-locale/build/ext-locale-zh_CN.js"></script>
    <link href="/ext/packages/ext-theme-crisp/build/resources/ext-theme-crisp-all.css" rel="stylesheet" />
</head>

<body></body>
<script>
Ext.onReady(function() {
    //模型描述
    Ext.define('User', {
        extend: 'Ext.data.Model',
        fields: [{
            name: 'firstName',
            type: 'string'
        }, {
            name: 'lastName',
            type: 'string'
        }, {
            name: 'age',
            type: 'int'
        }, {
            name: 'eyeColor',
            type: 'string'
        }]
    });

    //仓库整合
    Ext.define('UserStore', {
        extend: 'Ext.data.Store',
        model: "User",
        data: [{
            firstName: 'Ed',
            lastName: 'Spencer'
        }, {
            firstName: 'Tommy',
            lastName: 'Maintz'
        }, {
            firstName: 'Aaron',
            lastName: 'Conran'
        }, {
            firstName: 'Jamie',
            lastName: 'Avins'
        }]
    });

    var store = Ext.create('UserStore');

    Ext.create('Ext.grid.Panel', {
        title: 'Simpsons',
        store: store,
        columns: [{
            text: 'firstName',
            dataIndex: 'firstName'
        }, {
            text: 'lastName',
            dataIndex: 'lastName'
        }, {
            text: 'age',
            dataIndex: 'age'
        }, {
            text: 'eyeColor',
            dataIndex: 'eyeColor'
        }],
        listeners: {
            itemclick: function() {
                console.log('click el2');
            }
        },
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
    });


});
</script>

</html>

通过Sencha初始化+一个栗子的代码,虽然这养完成了任务,但只用到了组建,还没有用到更为重要的框架

mvc

跟着网上的呆毛,不明觉厉的使用方式

model:

Ext.define('app.model.User', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'firstName',
        type: 'string'
    }, {
        name: 'lastName',
        type: 'string'
    }, {
        name: 'age',
        type: 'int'
    }, {
        name: 'eyeColor',
        type: 'string'
    }]
});

controller:

Ext.define('app.controller.User', {
    extend: 'Ext.app.Controller',
    init: function() {
        this.control({
            'userlist': {
                itemclick: this.userlistHighlight
            }
        });
    },
    userlistHighlight: function() {
        console.log('click el');
    }
});

view:

Ext.define("app.view.user.List", {
    extend: "Ext.grid.Panel",
    alias: 'widget.userlist',
    store: Ext.create('app.store.User'),
    columns: [{
        text: 'firstName',
        dataIndex: 'firstName'
    }, {
        text: 'lastName',
        dataIndex: 'lastName'
    }, {
        text: 'age',
        dataIndex: 'age'
    }, {
        text: 'eyeColor',
        dataIndex: 'eyeColor'
    }]
});

Viewport:单页面入口

Ext.define("app.view.Viewport", {
    extend: "Ext.container.Viewport",
    layout: "fit",
    uses:['app.view.user.List','app.controller.User'],
    items: {
        xtype:"userlist"
    }
});

Application:架构启动

Ext.define('app.Application', {
    extend: 'Ext.app.Application',
    name: 'app',
    stores: [
        // TODO: add global / shared stores here
    ],
    controllers: ['User'],
    autoCreateViewport: true,
    launch: function() {}
});

通过Sencha初始化+上面的代码,就可以正确的运行了,混合了配置信息和异步加载信息等多种方式,组建的使用错误不大,但是架构的使用,略微蛋疼

1.uses是什么鬼?

一次性将所有js文件全部加载绝不是一个好主意,延迟加载/按需加载也就逐步转换为架构的一部分,而user与requires就是依赖元素(其中加载器中的require方法-.-毕竟干的都是一件事)

requires:初始化依赖文件,

uses:业务(初始化后)依赖文件

        createOverride: function (className, data, createdFn) {
            var me = this,
                overriddenClassName = data.override,
                requires = data.requires,
                uses = data.uses,
                mixins = data.mixins,
                mixinsIsArray,
                compat = data.compatibility,
                depedenciesLoaded,
                classReady = function () {
                    var cls, dependencies, i, key, temp;

                    if (!depedenciesLoaded) {
                        dependencies = requires ? requires.slice(0) : [];

                        if (mixins) {
                            if (!(mixinsIsArray = mixins instanceof Array)) {
                                for (key in mixins) {
                                    if (Ext.isString(cls = mixins[key])) {
                                        dependencies.push(cls);
                                    }
                                }
                            } else {
                                for (i = 0, temp = mixins.length; i < temp; ++i) {
                                    if (Ext.isString(cls = mixins[i])) {
                                        dependencies.push(cls);
                                    }
                                }
                            }
                        }

                        depedenciesLoaded = true;
                        if (dependencies.length) {
                            // Since the override is going to be used (its target class is
                            // now created), we need to fetch the required classes for the
                            // override and call us back once they are loaded:
                            Ext.require(dependencies, classReady);
                            return;
                        }
                        // else we have no dependencies, so proceed
                    }

                    // transform mixin class names into class references, This
                    // loop can handle both the array and object forms of
                    // mixin definitions
                    if (mixinsIsArray) {
                        for (i = 0, temp = mixins.length; i < temp; ++i) {
                            if (Ext.isString(cls = mixins[i])) {
                                mixins[i] = Ext.ClassManager.get(cls);
                            }
                        }
                    } else if (mixins) {
                        for (key in mixins) {
                            if (Ext.isString(cls = mixins[key])) {
                                mixins[key] = Ext.ClassManager.get(cls);
                            }
                        }
                    }

                    // The target class and the required classes for this override are
                    // ready, so we can apply the override now:
                    cls = me.get(overriddenClassName);

                    // We don't want to apply these:
                    delete data.override;
                    delete data.compatibility;
                    delete data.requires;
                    delete data.uses;

                    Ext.override(cls, data);

                    // This pushes the overridding file itself into Ext.Loader.history
                    // Hence if the target class never exists, the overriding file will
                    // never be included in the build.
                    me.triggerCreated(className);

                    if (uses) {
                        // This "hides" from the Cmd auto-dependency scanner since
                        // the reference is circular (Loader requires us).
                        Ext['Loader'].addUsedClasses(uses); // get these classes too!
                    }

                    if (createdFn) {
                        createdFn.call(cls, cls); // last but not least!
                    }
                };

            me.triggerExists(className, 2);

            if (!compat || Ext.checkVersion(compat)) {
                // Override the target class right after it's created
                me.onCreated(classReady, me, overriddenClassName);
            }

            return me;
        }

 requires属性下的js直接被加载,而uses下的js被加入usedclass方法,用以初始化完成后在加载

2.store: Ext.create('app.store.User')是什么鬼?

 创建/配置`仓库`,grid非常依赖的实例,很显然,creat代表着创建,每次加载grid都会创建一个store在内存中...为了达到复用目的(类似于create,show),可以使用StoreManage进行管理

3.Viewport

domcument.body的封装,代表整个浏览界面(body,所有没有renderto),主要用于方便布局,一个页面只有一个viewport

4.Application

应用程序的封装(类似于路由的全局封装),包含了应用程序应该绑定的Models、Views和Controllers,可以通过响应的属性进行管理(其实等价于requires),其中view可以被Controller管理(controller的效果依赖view的存在),所以这个地方需要描述Models和Controllers

当然了,application的配置又回在初始化时提前加载,所以是在view中使用requires分散压力,还是一口气配置完成,就看需求了

修改后标准的mvc:

Application:应用程序关联设置

Ext.define('app.Application', {
    extend: 'Ext.app.Application',
    name: 'app',
    stores: ['User'],
    controllers: ['User'],
    models:['User'],
    autoCreateViewport: true,
    launch: function() {}
});

viewreport:body的封装,无需在引用

Ext.define("app.view.Viewport", {
    extend: "Ext.container.Viewport",
    layout: "fit",
    items: {
        xtype:"userlist"
    }
});

view:真正的视图,完全找不到业务逻辑,如果页面需要修改,在此处

Ext.define("app.view.user.List", {
    extend: "Ext.grid.Panel",
    alias: 'widget.userlist',
    store: 'User',
    columns: [{
        text: 'firstName',
        dataIndex: 'firstName'
    }, {
        text: 'lastName',
        dataIndex: 'lastName'
    }, {
        text: 'age',
        dataIndex: 'age'
    }, {
        text: 'eyeColor',
        dataIndex: 'eyeColor'
    }],
    initComponent: function() {
        this.callParent();
    }
});

controller:真正的逻辑层,可以通过他来关联views(原因你懂得,实践胜于理论),如果逻辑出错,就在这里,依赖选择器

Ext.define('app.controller.User', {
    extend: 'Ext.app.Controller',
    views:['user.List'],
    init: function() {
        this.control({
            'userlist': {
                itemclick: this.userlistHighlight
            }
        });
    },
    userlistHighlight: function() {
        console.log('click el');
    }
});

至此mvc的方式就已经完成了,尽管聊过延迟加载,其实在mvc模式下,延迟加载的解决方案相当的糟糕-。-

mvvm

根据官网的呆毛,进行尝试

Application:应用程序关联设置

Ext.application({
    name: 'app',
    extend: 'app.Application',
    autoCreateViewport:'app.view.main.Main'

});

view容器:view木有任何逻辑,但参与调用/绑定的设计,以减少工作量,此处有迷之`main`参数,木有加载配置

Ext.define('app.view.main.Main', {
    extend: 'Ext.container.Container',
    xtype: 'app-main',
    controller: 'main',
    viewModel: {
        type: 'main'
    },
    layout: {
        type: 'border'
    },

    items: [{
        xtype: 'panel',
        bind: {
            title: '{name}'
        },
        region: 'west',
        html: '<ul><li>This area is commonly used for navigation, for example, using a "tree" component.</li></ul>',
        width: 250,
        split: true,
        tbar: [{
            text: 'Button',
            handler: 'onClickButton'
        }]
    },{
        region: 'center',
        xtype: 'tabpanel',
        items:[{
            title: 'Tab 1',
            html: '<h2>Content appropriate for the current navigation.</h2>'
        }]
    }]
});

controller:所有的逻辑都在这里,我们可以将alias注释掉,做几个小测试

Ext.define('app.view.main.MainController', {
    extend: 'Ext.app.ViewController',

    requires: [
        'Ext.window.MessageBox'
    ],

    // alias: 'controller.main',

    onClickButton: function () {
        Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
    },

    onConfirm: function (choice) {
        if (choice === 'yes') {
            //
        }
    }
});

vm:静态数据,此处可以添加各种get方法用以修改数据转换的逻辑

Ext.define('app.view.main.MainModel', {
    extend: 'Ext.app.ViewModel',

    // alias: 'viewmodel.main',

    data: {
        name: 'app'
    }

    //TODO - add data, formulas and/or methods to support your view
});

总之,vm+c分散了业务的代码

以上是官网的呆毛,如果根据这种格式去写第二个栗子就会发现,完全运行不起来。。。八层是该类未被加载的意思,但是,官网的例子又是为毛...

bootstrap.json-->可以在该文件下看见一下内容

        "app.view.main.MainController": {
            "idx": 17,
            "alias": ["controller.main"],
            "alternates": []
        },
        "app.view.main.MainModel": {
            "idx": 18,
            "alias": ["viewmodel.main"],
            "alternates": []
        }

在这里增加自己的测试项目,就可以相关像官网一样实现了

以上为ext下的mvvm实现,感觉也就是mvc+双向绑定,不如angular这种舒服

posted on 2015-11-09 12:03  Glimis  阅读(720)  评论(0编辑  收藏  举报