1

Sencha Touch 2 アプリを作成し、プロダクション モード バージョンをビルドしました。ただし、製品ビルドで大きな問題が発生し、電話/タブレット モードで実行されています。

ST2 の現在のプロファイルの実装には、特定のプロファイルを有効にしてもすべてのビューが読み込まれるため、欠陥があるようです。私のアプリケーションでは、ビュー構成で xtype エイリアスを使用してビューを指定し、正しいビューを使用できるようにしたいと考えています。特別なコーディングなしでロードされた電話またはタブレットのプロファイル用。プロファイルからのすべてのビューが読み込まれている場合、これは機能しません (1 つのビューが常に別のビューをオーバーライドします)。

これを達成できる唯一の方法は、次のように、起動段階 (app.js 内) でプロファイルを動的に追加することでした。

Ext.application({
    name: 'MyTestApp',

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

    requires: [ ... ],

    profiles: activeProfile

});

これはうまくいきました。これは、正しいビューをロードしても、別のビューの構成内で xtype エイリアスを使用したり、コントローラーで ref を使用したりできることを意味します。ただし、製品ビルドを生成してコンソール ウィンドウをロードすると、次の両方が定義されていることに気付きました。

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 が、実稼働モードのときにプロファイルに応じて正しいバージョンを取得するようにするにはどうすればよいですか?

4

3 に答える 3

2

いずれかのソリューションをデバイスに移動すると、すべてのビューが参照され、xtype の衝突が発生して常に電話ビューが表示されるという事実に悩まされていました。(最終的にはエイリアスに移行する必要がありました-理由はわかりません:( )。将来の参考のために共有するだけで、最終的に私のユースケースでこれをクラックすることができました。

touch 2.3.1 と cordova 3.3.1 を最新の cmd 4.0.2.67 で実行しています

app.js に保存するのではなく、sencha touch ソース ディレクトリのソース コードを変更する必要があったことを除いて、私は Christopher のソリューションを使用します [正直なところ、オーバーライドとして残しておくとハングする理由がわかりません]

さらに、ビューを次のように構成する必要がありました。

  • エイリアスを使用してビューの基本クラスを定義し、最初に読み込まれるときにコントローラーが参照を理解できるようにします
  • プロファイルによってインスタンス化されたビューにエイリアスを動的に割り当てます
  • 取り除く (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');
       }
    });

タブレット ビューについても繰り返します

于 2014-03-08T14:26:57.480 に答える
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)
        }
    }
});

次に、基本クラスからプロファイル クラスを継承します (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 名は実行時に解決されます。

このコードを改善したり、これを行うためのより良い方法にしたりできると確信しています。お気軽にお知らせください。

于 2013-04-23T21:35:11.530 に答える
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 を定義する必要があります。そうすれば、コントローラーの参照も機能します...

これでテストを続ける必要がありますが、これまでのところ有望に見えます。

于 2013-09-25T06:57:24.390 に答える