2

かなり複雑なバックボーンアプリケーションがあり、ビュー/テンプレートを整理する方法がわかりません。アプリケーションはWebベースの電子メールクライアントです。このサイドバーの作り方を理解するのに本当に苦労しています。

アプリケーションのサイドバーは、Apple Mail/Outlookに表示されるものと非常によく似ています。基本的にはフォルダブラウザです。このビューは各ページにあります。

私には2つの主な問題があります:

収集データをサイドバービューに取り込むにはどうすればよいですか?

サイドバーに表示される技術的には3つの「コレクション」があります-アカウント=>メールボックスとラベル。したがって、いくつかのサンプルコードは次のようになります。

<div class="sidebar">
  <div class="sidebar-title">Mailboxes</div>

  <div class="sidebar-subtitle">Gmail</div>
  <div class="mailboxes" data-account-id="1">
    <ul>
      <li><a href="...">Inbox</a></li>
      <li><a href="...">Sent</a></li>
      ...
    </ul>
  </div>

  <div class="sidebar-subtitle">Yahoo</div>
  <div class="mailboxes" data-account-id="2">
    <ul>
      <li><a href="...">Inbox</a></li>
      <li><a href="...">Sent</a></li>
      ...
    </ul>
  </div>

  <div class="sidebar-title">Labels</div>
  <div class="sidebar-labels">
    <ul>
      <li>Home</li>
      <li>Todo</li>
    </ul>
  </div>
</div>

だから理論的には私はこのようなことをする必要がありますね

<div class="sidebar">
  <div class="sidebar-title">Mailboxes</div>

  <% for account in @accounts.models: %>
    <div class="sidebar-subtitle"><%= account.get('name') %></div>
    <div class="mailboxes" data-account-id="<%= account.get('id') %>">
      <ul>
        <% for mailbox in account.mailboxes.models: %>
          <li><a href="..."><%= mailbox.get('name') %></a></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="sidebar-title">Labels</div>
  <div class="sidebar-labels">
    <ul>
      <% for label in @labels: %>
        <li><%= label.get('name') %></li>
      <% end %>
    </ul>
  </div>
</div>

@accounts問題は、ルーターからとルーターの両方を通過できないこと@labelsです。私は使用できることに気づき@optionsましたが、それは厄介でバックボーンではないようです。このサイドバーは、各ページに存在する必要があります。バックボーンスタックではどのように見えるべきですか?それは実際には「ページ」ではないので、独自のルーターを持つべきではないと思います。

物事をより小さなビューに分割しますか?

各メールボックスは独自のビューである必要がありますか?各メールボックスは独自のビューである必要がありますか?それぞれが独自のビューにラベルを付けますか?新しいメッセージなどのイベントをリッスンし、メールボックスの未読数を更新したい(たとえば)。しかし、どうすればこれを行うことができますか?ビューをネストして、すべてのオブジェクトの作成/フェッチを効率的に処理するにはどうすればよいですか?物事をより小さなビューに分割する場合、サイドバービューはどのようになりますか?

とりとめのない場合は申し訳ありません。私はこれを何日も見てきましたが、良い解決策を見つけることができないようです。

4

1 に答える 1

6

使用optionsは完全に合法であり、Backbone-yです。ですから、これを利用する方法は他にもたくさんありますが、私はそれを利用することを恐れません。うん。サイドバーは、ルーターによって呼び出される大きなページビュー内で初期化する必要があると思います。

また、メールボックスは独自のサブビューである必要があると思います。メールがyahooかgoogleかに関係なく、各メールボックスは同じ機能(最小化など)を持っているように聞こえるので、そのビュークラスを作成して複数回再利用することは非常に理にかなっています。

では、このメールボックスビューは何を取るべきでしょうか?(コレクションに関して)

繰り返しますが、選択肢があります。すべてを含む1つの大きなコレクションを投入するか、あるタイプのアカウントからのメールを表す各コレクションを投入します...

コレクションがすでに分離されている場合(たとえば、Googleメール用に1つ、Yahooメール用に1つ)、サブビューを作成して適切なコレクションをそれぞれに渡すのは簡単です。分離されていなくても、コレクションとして渡す前に、必要なモデルだけにコレクションをフィルタリングすることになるでしょう。これが私が傾倒するものです。各メールボックスビューで、そのメールボックスが特定のアカウントに関連付けられていないメールモデルにアクセスする必要があるという状況は決してないと思います。したがって、不要なものを渡すことは意味がありません。

ラベルに関しては、よくわかりません。それはあなたのレーベルが何にどのようになっていくかによると思います。たとえば、基本的にメールmodel.idに関連付けられたラベルタグである独自のラベルモデルがありますか?または、ラベルは、摘み取っているメールモデルの属性ですか?

サンプルコードによる更新-ビュー階層を介したデータの受け渡しに焦点を当てる

したがって、ここでは基本的に、親ビュー内に子ビューを作成する非常に一般的なタイプの方法と、ビューの階層を介してさまざまなデータ(この場合はコレクションを参照)を渡す方法の概要を説明します。

これをさらに多くの子ビューに対して行うことができます(各メールモデルには、メールボックスビュー内のリストアイテムとして独自の代表的な子ビューがあるなど)。パターンを繰り返し、[options]Viewコンストラクターの引数を利用して、内側でそれを受け入れます。

このコードの多くの部分で、どのデータがどこに渡されるかを正確に透過的にするために、私は長い間アプローチをとっています。子ビューを追加する方法のポイントを示すために、メールボックステンプレートを少し変更しましたが、元に戻すことはできます。MailboxViewで何をするかはあなた次第であり、コード(目標に応じて)はそれを反映する必要があります。

ですから、これ以上面倒なことはせずに、これを噛み砕いて考えるためのサンプルコードをいくつか示します。エラーが発生する可能性があるため、これを一緒にホイップしました。それが実行されるかどうかは実際にはわかりませんでした。

通常、ビューでは、view.elをテンプレートの最も外側の要素として定義し、内側の部分のみを含めますが、提供したテンプレートを維持し、コード内の混乱を招く可能性のある余分なものの数を減らすために、Iほとんどの場合、テンプレートはそのままにしておきます。

// Your templates
<script id="sidebar" type="text/template">

    <div class="sidebar">
    <div class="sidebar-title">Mailboxes</div>
        // Mailbox here
        // Mailbox here
        // Labels  here
    </div>

</script>

// I altered this template slightly just to illustrate a point on appending the model
// view data into your mailbox view. You might not want this but it's just for
// demonstration purposes
<script id="mailbox" type="text/template">
    <div class="sidebar-subtitle">Gmail</div>
    <div class="mailboxes" data-account-id="1">
        <ul class="inbox"></ul>  // Changed this
        <ul class="sent"></ul>
    </div>
</script>

<script id="labelBox" type="text/template">
    <div class="sidebar-title">Labels</div>
        <div class="sidebar-labels">
            <ul>
                <li>Home</li>
                <li>Todo</li>
            </ul>
        </div>
    </div>
</script>

アプリケーションのBIGビュー、すべてを網羅するメインビュー。

AppView = Backbone.View.extend({
    initialize: function() {
        // You might not instantiate your collections here but it is a good starting
        // point for this demo. We'll be passing these through children view and 
        // utilizing them in the appropriate views.

        // Let's assume these collections we instantiate already have models inside them.

        // Your 3 Collections
        this.gmail = new MailCollection();
        this.yahoo = new MailCollection();
        this.labels = new LabelCollection();

    },
    render: function() {
        this.$el.html();

        // We pass each collection into the SidebarView [options] hash. We can "pick-up"
        // these collections in the sidebar view via this.options.xxx

        // Render the sidebar
        var sidebar = new SidebarView({
            'gmail':this.gmail,
            'yahoo':this.yahoo,
            'labels':this.labels
        });

        // Render the sidebar and place it in the AppView... anywhere really
        // but for simplicity I just append it to the AppView $el
        this.$el.append(sidebar.render().el);

        return this;
    }
});

サイドバービュー:

SidebarView = Backbone.View.extend({
    template: _.template($('#sidebar').html()),
    initialize: function() {

        // We passed the 3 collections into Sidebar view and can access
        // them through the options. We could have instantiated them here
        // but I passed them into the side to illustrate that using
        // options for this kind of thing is a-okay.

        this.gmail = this.options.gmail,
        this.yahoo = this.options.yahoo,
        this.labels = this.options.labels

        // This is an array of sub-view mailboxes so when we close this view,
        // it's easy to loop through the subviews and close both mailboxes
        this.mailboxes = [];
    },
    render: function() {
        // We render the sidebarView using the template
        this.$el.html(this.template());

        // We generate the sub-view mailbox views (gmail and yahoo)
        var gmailView = new MailboxView({
            'collection': this.gmail // We pass in only the gmail collection
        });
        var yahooView = new MailboxView({
            'collection': this.yahoo // Pass in the yahoo mail collection
        });
        var labelView = new LabelboxView({
            'collection': this.labels // Pass in the labels collection
        });

        // We push the views into our array
        this.mailboxes.push(gmailView);
        this.mailboxes.push(yahooView);
        this.mailboxes.push(labelView);

        // Render each view and attach it to this sidebar view
        this.$el.append(gmailView.render().el);
        this.$el.append(yahooView.render().el);
        this.$el.append(labelView.render().el);

        return this;
    },
    onClose: function() {
        // Sample code of how we close out child views. When this parent view closes,
        // it automatically cleans up the child views.

        _.each(this.mailboxes, function(view) {
            view.close(); // A special function that I use to close views
        });
    }
});

私が使用する方法と方法の詳細については、ゾンビビューのクリーンアップを参照してください。アプリで多くのビュー/サブビューの関係を作成し始めたら、特に役立ちます。onClose()close()

メールボックスビュー:

MailboxView = Backbone.View.extend({
    template: _.template($('#mailbox').html()),
    initialize: function() {
        // When we pass something in as 'collection' backbone automatically
        // attaches it as a property of the view so you can use the collection
        // as this.collection rather than this.options.collection for
        // convenience
    },
    render: function() {
        this.$el.html(this.template());

        this.loadMail();

        return this;
    },
    loadMail: function() {
        // Some code that loops through your collection and adds the mail to an
        // appropriate DOM element. Would make sense to make Inbox a ul and each
        // mail an li so I altered your template to demonstrate this

        // Let's assume a mail model has the attr 'author' and 'body' in this
        // simple example

        // This will loop through your collection and use a mail template to
        // populate your list with the appropriate data.
        this.collection.each(function(mail) {
            this.$('ul').append(_.template('<li><%=author%><%=body%></li>', mail.toJSON()))
        });

        // Alternatively, you could (and probably should) make each mail model
        // represented by ANOTHER sub-view, a mail subview that has all the
        // functionality that mail views usually have.
        // To accomplish this you just repeat the prior demonstrated cycle
        // of creating child view inside child view, passing in the appropriate
        // data that you need, creating the view, and attaching it to the parent
        // where you would like.
    }
});

あなたのLabelsView:

LabelboxView = Backbone.View.extend({
    template: _.template($('#labelBox').html()),
    initialize: function() {
        // I think you get the gist from above, you'd do the same thing as each
        // mailbox view except deal with the unique aspects of labels, whatever
        // these may be (and do)
    },
    render: function() {
        this.$el.html(this.template());
        return this;
    }
});  
于 2012-09-10T00:56:44.167 に答える