Ext JS と Sencha Touch のレイアウトシステムを探る
こんにちは、ゼノフィnakamuraです。
レイアウトシステムは、Sencha フレームワークの最もパワフルでユニークな部分です。 レイアウトはアプリケーションの中にある各コンポーネントのサイズや位置を調整します。 Ext JS と Sencha Touch は類似点が沢山ありますが、 Ext JS 5 ではタブレットもサポートされるようになりました。 Sencha フレームワーク全体で、レイアウトシステムがどんな風に動作しているのかを見ていきましょう。
レイアウトのお話
HTMLではレイアウトシステムを厳密に定義するには機能が不足しています。 何年もの間、 複数のブラウザーで同様に描画される Webサイトやアプリケーションを開発することは、 CSS 実装の違いにより非常に難しいものでした。 ベテランの開発者なら、シンプルな2カラムレイアウトを実現するために、プラットフォームごとに違う “float” ルールを書かなければならなかったことを思い出すことでしょう。
Ext JS や Sencha Touch を含めたフレームワークは、 そのようなクロスブラウザ問題を軽減し、 つまらない CSS の違いに費やす時間を軽減して、 より多くの時間を機能の追加に費やすことができるようになります。 新しいHTMLやCSS標準は成熟し、ブラウザベンダーによって採用されました。 Sencha フレームワークもまた、レガシーブラウザとの後方互換性を維持しつつ、これらの標準をサポートするようになりました。
Ext JS 5 と Sencha Touch は抽象的なクロスプラットフォームなレイアウトシステムを提供します。 これは内部的には違った方法で実現されていますが、表面上の API はほとんど同じになっています。 一般的なアイデアは、クリーンで簡潔な JavaScript API を使って、複雑なレイアウトを実装する時のうんざりするような仕事をなくすことです。
Sencha アプリケーションはコンポーネントからなります。 コンテナーは、いろいろな「レイアウト」で、他のコンポーネントを内部に配置できる特別なコンポーネントです。 コンテナーやコンポーネントを重ね合わせることで、クロスブラウザのおかしな動きに気をとらわれることなく、堅牢なインターフェースを素早く簡単に構築できます。
相似点
Ext JS と Sencha Touch は違ったプラットフォームをターゲットにしていますが、どちらも HTML5 フレームワークであり、多くの高レベルなコンセプトは共通です。 Webアプリを構築するパラダイムは Ext JS と Sencha Touch で共通なので、どちらかになじみのある開発者は、もう一方も簡単に理解できます。 レイアウトも例外ではありません。
次のレイアウトが Sencha Touch 2.3.1 と Ext JS 5.0.0 beta の双方でサポートされます。
Fit
一つの子アイテムが親の全てのスペースを占有します。 (Touch)(Ext JS)
Card
Fit と同様ですが、複数の子アイテムを持ち、そのうちの一つだけが表示されます。タブパネルとして使われます。 (Touch)(Ext JS)
HBox
子アイテムは水平に配置されます。 (Touch)(Ext JS)
VBox
子アイテムは垂直に配置されます。 (Touch)(Ext JS)
Float (Touch) / Absolute (Ext JS)
子アイテムは top/left または x/y 座標で位置指定されます
これらのレイアウトを用いるときの JavaScript API は、Ext JS と Sencha Touch でほぼ同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Sencha Touch 2.3.1 Ext.create('Ext.Container', { layout : 'hbox', items : [ //... ] }); // Ext JS 5.0.0 Ext.create('Ext.container.Container', { layout : 'hbox', items : [ //... ] }); |
ご覧のように、Ext JS と Sencha Touch の API ではちょっとした違いがありますが、レイアウトに関連する API は基本的に同じです。
相違点
Ext JS と Sencha Touch では、サポートするデバイスの範囲が大きく違います。 主にターゲットプラットフォーム特有の UI/UX に配慮してレイアウトシステムの違いがあります。
Ext JS は、歴史的にデスクトップコンピュータ用でしたが、Ext JS 5 ではタブレットもサポートします。 一方、 Sencha Touch はよりモバイルデバイス (スマートフォン、タブレット、などのタッチスクリーンデバイス) に適したものになっています。
その結果、それぞれのフレームワークのレイアウトシステムに違う部分があります。 最も大きく違うところは、あるレイアウトクラスは一方にあって、もう一方にはないという点です。(以下を参照) もう一つの違いは見えにくいのですが、共通のレイアウトが、HTMLレベルではそれぞれで全然違うやりかたで実装されている点です。
Ext JS のみのレイアウト
Border
ほとんどのアプリの典型的な最初のレイアウトで、north, south, east, west, center のリージョンがあります。Viewport によく設定されます。 (Ext JS)
- Sencha Touch では、同じ様なことをする、”docking” コンポーネントをサポートします。 (Touch)
Table
子アイテムは行と列で配置されます。 (Ext JS)
Column
HBox や 行のない Table レイアウトと同様です。 (Ext JS)
Anchor
VBox と同様ですが、スクロールするコンテンツ向けです。 (Ext JS)
Form
Center
一つの子アイテムを親の中央に配置します。 (Ext JS)
Ext JS 5 と Sencha Touch での HBox の比較
Box レイアウトはたぶん、Ext JS でも Sencha Touch でも最もポピュラーなレイアウトです。簡単に使えて、コンポーネントを水平/垂直に配置する場合にはとてもパワフルです。 Box レイアウトはコンポーネントの水平/垂直のサイズを自動的に調整します。 特に (“flex” コンフィグによって) コンポーネントをフレキシブルな高さ/幅にする必要があるときに力を発揮します。
Ext JS と Sencha Touch が HBox の同じコンセプトをそれぞれ違う方法で実現しているやり方を、掘り下げてみましょう。
二つのコンポーネントがコンテナーの中に水平に配置される、というシナリオを考えてください。
JavaScript コードは、Ext JS 5 と Sencha Touch でほとんど同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | { xtype : 'container', layout : 'hbox', style : 'background: gray;', padding : 10, defaults: { xtype : 'component', height : 100 }, items: [{ style : 'background: yellow;', width : 100 }, { style : 'background: green;', flex : 1 }] } |
同じサンプルを、Sencha Fiddle でも見ることができます。
- Ext JS 5: https://fiddle.sencha.com/#fiddle/4uv
- Sencha Touch: https://fiddle.sencha.com/#fiddle/4v0
さて、カーテンの裏側を覗いて、フレームワークが実際のDOM をどのように描画しているかを (Google Chrome を使って) 見てみましょう。
まず、 Ext JS 5 のマークアップから見てみます。
二つの DIV タグは、それぞれ黄色と緑の四角です。
スクリーンショットにはありませんが、両方とも
position: absolute
がセットされています。
二つ目の DIV に
left: 100px
と
width: 493px
がセットされているのに注目してください。
前の JavaScript コードを見ると、 黄色のコンポーネントでは、width を 100px に設定していますが、 緑のコンポーネントには、”flex” を使って残りの幅を (この場合だと 493px) を全て割り当てようとしています。 Ext JS はすべての計算をやってくれるので、クロスブラウザ問題に悩まされずに済みます。 (“計算された” レイアウトのアイデアについては後ほど再び触れましょう)
では、 Sencha Touch のマークアップを見てみましょう。
ここでも二つの DIV タグ (黄色と緑の四角) があります。
二つ目の DIV タグに
webkit-box-flex: 1
という設定がありますね。
スクリーンショットにはありませんが、親の DIV タグには、
display: -webkit-box;
がセットされています。
CSS3 の flexbox についてご存じでしょうか。 flexbox は、全てのモダンブラウザで実装されている非常に便利な CSS3 仕様です。 flexbox では、 さまざまな方法で子アイテムを配置したりサイズを整えたりすることが簡単にできます。 これは以前は沢山の HTML や CSS をトリッキーに組み合わせる必要がありました。
従って、Sencha Touch は、緑のコンポーネントの “flex” の計算を、JavaScript を使って手動でエレメントの位置を計算する代わりに、ブラウザのネイティブレイアウトエンジン (CSS flexbox によって) に任せてしまいます。
とすると疑問に思うのは、「なぜ Ext JS は CSS3 を使わないのか?」 という点です。
この答えは簡単です。プラットフォームをサポートするためです。 Sencha Touch は モバイルブラウザのみを対象にしていて、 サポートするプラットフォームの全てが CSS3 の flexbox 仕様を実装しています。 Ext JS 5 は多くのレガシーブラウザをサポートしていて、 下の図 にあるように、CSS3 の flexbox をサポートしていないブラウザがまだまだ沢山使われています。
この事実を補うために フレームワークは時間をかけてレイアウトを計算します。 Ext JS では、実行時にいつでも レイアウトのサスペンドと再会 することをサポートしています。
1 2 3 | Ext.suspendLayouts(); // do stuff... Ext.resumeLayouts(true); |
この最適化テクニックを使うと、DOM ツリーに対して一度に多くの変更がなされることを避ける事ができるので、Ext JS のパフォーマンスを向上することができます。 これは、デスクトップコンピュータに較べてプロセッサが貧弱な (タブレットなどの) モバイルデバイスにおいてより重要です。
まとめ
ご覧のように、それぞれのフレームワークのレイアウト実装を駆動するのは、ターゲットプラットフォームがサポートするWeb標準です。 Ext JS 5 では Sencha Touch で動作しているコンセプトを借りて、タブレットサポートを拡大するために、多くのステップを実行しています
Ext JS と Sencha Touch の二つは内部処理に違いがあるにもかかわらず、 二つのフレームワークは変わらない API を持ち、多くのライブラリの他のコアパーツ (データ、チャートなど) を共有しています。 詳しくは、 What’s New in Ext JS 5 ガイドを参照してください。