Eyes, JAPAN Blog > 親子関係で困ったこと

親子関係で困ったこと

yahata

この記事は1年以上前に書かれたもので、内容が古い可能性がありますのでご注意ください。

ちょっと前から、会社とは別のところで結構規模の大きなwebアプリケーションを作っています。
Backbone.jsで土台を組んで、Ajaxバリバリのモダンな感じです。

webアプリケーションを作るときのview構造について、簡単な例を挙げてみます。

uml

すごく簡単なview構造の例です。一般的なwebページは、大体こんな感じの構造になっているでしょう。
ここで、「グローバルナビでクリックされたボタンに従って、ユーザーリストの内容を書き換える」という処理をしたいと思います。

uml2

すると、イベントの流れは上のようになります。
この場合、クリックイベントはAの向きに流れ、書き換え命令イベントはBの向きに流れています。
より詳細に解説すると、以下のような事が起きています。

  1. グローバルナビでクリックイベントが発生する
  2. グローバルナビviewはクリックイベントをキャッチする
  3. グローバルナビviewはヘッダーviewにクリックイベントを委譲する
  4. ヘッダーviewはルートviewにクリックイベントを委譲する
  5. ルートviewはメインコンテンツviewに書き換え命令を下ろす
  6. メインコンテンツviewはユーザーリストviewに書き換え命令を下ろす
  7. ユーザーリストが書き変わる

うーんシンプル!直感的に分かりやすい流れですね。

僕はしばらくの間、この設計に何の疑いも持たずに開発を行っていました。
が、これだと一つ大きな問題点があります。

Aの向き(上向き)のイベントは、DOMのイベントバブリングの仕組みを利用できるため、ヘッダーviewなど間のviewに特別なメソッドを作らなくても流れてくれます。
しかし、Bの向き(下向き)のイベントは、メインコンテンツviewなど間のviewに特別なメソッドを作らないといけないのです。

viewの階層が深くなってくると、「間のviewでは何もしないのに、ただイベントを下ろすためだけに特別なメソッドを作らないといけない」という感じで無駄なメソッドがどんどん増えていき、結構なコストに感じてきます。
そこで、色々調べながら見つけたのが下の設計です。

uml3

「グローバルナビイベントリスナー」というイベントリスナを用意しておき、グローバルナビviewとユーザーリストviewの2つを初期化するときに、2つのviewをイベントリスナに登録しておきます。
クリックイベントはまずイベントリスナに委譲され、それからイベントリスナに登録しておいたユーザーリストviewにイベントが流れていきます。

こうすることで、2つのviewはお互いの存在を意識することなく、しかも、viewの階層が深くなっても無駄なメソッドを増やすことなく処理を済ませることができるのです!

でも、どっちがいい設計なのか未だに迷っています。最初のパターンの方が親子関係を崩さずに済むというメリットもあるし、悩ましいですね。
何か良い案があれば教えていただけると嬉しいです。

前者のコード:http://jsdo.it/oimou/ztHK
後者のコード:http://jsdo.it/oimou/x9jK

担当:八幡(CoffeeScriptよいです)

Comments are closed.