Sencha Touch 2中的配置文件功能会在生产模式构建中导致问题

时间:2013-03-30 18:05:50

标签: sencha-touch-2 sencha-touch-2.1

我创建了一个Sencha Touch 2应用程序并构建了一个生产模式版本。但是,我遇到了生产版本的一个大问题,它在手机/平板电脑模式下运行。

ST2的当前配置文件实现似乎有缺陷,即使您激活了特定的配置文件,所有视图仍然被加载。在我的应用程序中,我希望能够在视图配置中使用xtype别名指定视图,并且没有任何特殊编码的手机或平板电脑配置文件的正确视图。如果加载了配置文件中的所有视图,则无法使用(一个视图将始终覆盖另一个视图)。

我能实现这一目标的唯一方法是在启动阶段(在app.js内)动态添加配置文件,如下所示:

Ext.application({
    name: 'MyTestApp',

    var activeProfile = Ext.os.is.Phone ? ['Phone'] : ['Tablet'];

    requires: [ ... ],

    profiles: activeProfile

});

这很好用。这意味着我可以加载正确的视图,仍然只是在另一个视图的配置中使用xtype别名和/或在控制器中引用。但是,我注意到当我生成生成构建并加载控制台窗口时,定义了以下两个:

MyTestApp.views.phone.Login
MyTestApp.views.tablet.Login

通常,平板电脑或手机版本将根据配置文件未定义。我假设是这种情况,因为生产模式构建已经解析了所有依赖项,然后包括所有视图而不管配置文件。

所以在我的启动控制器中,我有一个按钮处理程序,然后从xtype创建一个登录视图。

控制器:

refs: {                
            loginView: {
                selector: 'loginview',
                xtype: 'loginview',
                autoCreate: true
            }
 }

处理程序:

var loginView = this.getLoginView();

在开发模式下,loginView变量将是 MyTestApp.views.tablet.Login MyTestApp.views.phone.Login ,具体取决于配置文件。

在生产模式下,如何确保此处实例化的loginview获取正确的版本,具体取决于配置文件?

3 个答案:

答案 0 :(得分:2)

我一直在努力解决这个问题,当我将任何一个解决方案移动到设备上时,我会坚持所有视图都被引用的事实,并且会得到一些xtype碰撞总是给我电话视图。 (我不得不最终转移到别名 - 不知道为什么:()。我终于设法破解了我的用例,只是分享以供将来参考。

我正在运行touch 2.3.1和cordova 3.3.1以及最新的cmd 4.0.2.67

我使用克里斯托弗的解决方案,除了我必须更改sencha触摸源目录中的源代码而不是将其保存在app.js中[实际上我不知道为什么它在我将其作为覆盖时挂起]

此外,我必须按以下方式配置视图:

  • 使用别名为视图定义基类,以便控制器在首次加载时理解ref
  • 动态地将别名分配给由配置文件实例化的视图
  • 剥离(使用Christopher代码)

视图的基类

    Ext.define('MyApp.view.CatalogView', {
        extend: 'Ext.Container',
        alias: 'widget.catalogview'
    });        

为配置文件特定视图指定别名

    Ext.define('MyApp.profile.Phone', {
        extend: 'Ext.app.Profile',

        config: {
            name: 'Phone',
            views: ['CatalogView'],
        },

       isActive: function() {
           return Ext.os.is('Phone');
       },

       launch: function() {
           Ext.ClassManager.setAlias('MyApp.view.phone.CatalogView', 'widget.catalogview');
       }
    });

重复播放平板电脑视图

答案 1 :(得分:1)

对于所有想知道我是如何解决这个问题的人来说,现在我把头发拉出来之后就会秃顶;)

我希望拥有xtype名称的所有个人资料视图保持不变,即使它们可能属于手机或平板电脑配置文件,我必须删除该类上的别名/ xtype配置。然后,我使用共享帮助函数定义了一个配置文件基类:

Ext.define('MyApp.profile.Base', {
    extend: 'Ext.app.Profile',

    config: {

    },

    mapViewAliases: function () {
        var self = this;

        var views = this.getDependencies().view;
        var newAliasMap = null;

        Ext.each(views, function (view) {
            Ext.Array.some(self.getViewsToAliasMap(), function (map) {
                if (map[view]) {
                    if (!newAliasMap) {
                        newAliasMap = {};
                    }

                    newAliasMap[view] = [map[view]];                    
                    return true;
                }
            });
        });

        if (newAliasMap) {
            console.log('view aliases being mapped for: ' + this.$className);
            Ext.ClassManager.addNameAliasMappings(newAliasMap)
        }
    }
});

然后我从基类继承了profile类(除了viewsToAliasMap包含属于平板电脑配置文件而不是电话配置文件的类之外,这与平板电脑配置文件一起重复):

Ext.define('MyApp.profile.Phone', {
    extend: 'MyApp.profile.Base',

    config: {
        name: 'Phone',
        views: ['Login', 'Home', 'Welcome' ],

        viewsToAliasMap: [
             { 'MyApp.view.phone.Login': 'widget.loginview' },
             { 'MyApp.view.phone.Home': 'widget.homeview' },
             { 'MyApp.view.phone.Welcome': 'widget.welcomeview' }
        ]
    },

    isActive: function () {
        return Ext.os.is.Phone;
    },

    launch: function () {
        console.log("Phone profile launched");

        this.mapViewAliases();

    }
});

基本上,配置文件在启动函数的基类上调用函数mapViewAliases()。 mapViewAliases()使用类管理器将配置文件中定义的别名注册到视图类名称。因此,有效地在运行时解析xtype名称。

我确信这段代码可以改进和/或更好的方法。 请随时告诉我。

答案 2 :(得分:0)

我正在使用一个非常天真的实现......我确信它可以变得更强大,但我现在已经黑了5个小时了。

Ext.define('MyApp.override.Application', {
    override : 'Ext.app.Application',

    onProfilesLoaded: function() {
        var profiles  = this.getProfiles(),
            length    = profiles.length,
            instances = [],
            requires  = this.gatherDependencies(),
            current, i, profileDeps;

        for (i = 0; i < length; i++) {
            var instance = Ext.create(profiles[i], {
                application: this
            });

            /*
             * Note that we actually require all of the dependencies for all Profiles - this is so that we can produce
             * a single build file that will work on all defined Profiles. Although the other classes will be loaded,
             * the correct Profile will still be identified and the other classes ignored. While this feels somewhat
             * inefficient, the majority of the bulk of an application is likely to be the framework itself. The bigger
             * the app though, the bigger the effect of this inefficiency so ideally we will create a way to create and
             * load Profile-specific builds in a future release.
             *
             CMK - PSHAW!
             */

            if (instance.isActive() && !current) {
                console.log('Profile active: ' + instance.getName());
                current = instance;

                profileDeps = instance.getDependencies();
                requires = requires.concat(profileDeps.all);
                var ns = instance.getNamespace();

                this.setCurrentProfile(current);

                // Merge Controllers, Models, Stores, and Views
                this.setControllers(this.getControllers().concat(profileDeps.controller));
                this.setModels(this.getModels().concat(profileDeps.model));
                this.setStores(this.getStores().concat(profileDeps.store));
                this.setViews(this.getViews().concat(profileDeps.view));

                // Remove the view ref and requires for default views, when a profile specific one exists
                Ext.each(profileDeps.view, function(className) {
                    if (className.indexOf('view.' + ns + '.') !== -1) {

                        // Requires
                        var index = requires.indexOf(className.replace('view.' + ns, 'view'));
                        if (index !== -1) {
                            requires.splice(index, 1);
                        }
                        // Views
                        index = this.getViews().indexOf(className.replace('view.' + ns, 'view'));
                        if (index !== -1) {
                            this.getViews().splice(index, 1);
                        }
                    }
                }, this);

                instances[0] = instance;
                break;
            }
        }

        this.setProfileInstances(instances);
        Ext.require(requires, this.loadControllerDependencies, this);
    }
});

将它放在Ext.application之前,它取代了配置文件加载器......这个删除了与活动配置文件命名空间中的默认视图名称相同的默认视图。

它要求你为匹配的视图定义一个xtype,那么即使你的控制器中的ref也可以工作......

我需要继续测试,但到目前为止看起来很有希望。