4

I'm making a toy app, trying to learn about these libraries and was hoping to understand how I would present a "tab" interface. I'd like to have a few buttons (or links, whatever is most common) on top. When one selected, it looks selected and the main content on the page changes to present what's on that tab.

My learning app is very simple at the moment:

<body>
    <div class="content"></div>
</body>

And a backbone view:

var ContentView = Backbone.View.extend({
    el: $('.content'),
    // ..

So far, I've looked into using <% tag in the html to make a partial, making the ContentView somehow responsible for rendering different stuff in there. The other idea I've had but don't quite know how to pursue is several Backbone views taking turns being in charge of changing the one div.

Would sure appreciate some advice about the canonical approach here, including how to present the tabs buttons and how to cleanly separate view logic for the different tabs.

4

1 回答 1

5

Follow a 'separation of concerns' model. You've got a main content view, which handles tab navigation. Anytime someone clicks on a tab, that main content view should tell the view that the tab belongs to that it is now active. Then that sub-view handles things from there. Here's some example code:

Let's say this is the HTML:

<div id="tabContainer" class='tabs'>
    <div class='tab' id="content1Tab"></div>
    <div class='tab' id="content2Tab"></div>
    <div class='tab' id="content3Tab"></div>
</div>
<div id="contentContainer">

</div>

This might be the javascript.

ContentView = new (Backbone.View.extend({}
    events: {
        'click .tab': 'openTab'
    },

    el: $("#tabContainer"),

    tabViews: {},

    openTab: function (e) {
        var el = $(e.currentTarget);
        $("#contentContainer").children().detach();

        if(!this.tabViews[el.attr('id')]) {
            this.tabViews[el.attr('id')] = this.createTabViewForEl(el);
        }

        this.tabViews[el.attr('id')].render($("#contentContainer"));
    },

    createTabViewForEl: function (el) {
        var tab;
        switch(el.attr('id')) {
            case "content1Tab":
                tab = new FirstContentTab();
                break;
            /* etc */
        }
        return tab;
    }
))();

FirstContentTab = Backbone.View.extend({
    render: function (targetEl) {
        this.setElement($("#someContentEl"));
        this.$el.appendTo(targetEl);
    }
    /** stuff like loading in content for tab, or making a monkey dance when it opens **/
});

There are more elegant ways of doing this, like referencing the module that the tab belongs to, then using requirejs or some other module loader to load in that module and give it the tab in question. But, either way, don't let that one main view do too much. Otherwise you'll end up with something that's way more complicated than it needs to be.

于 2013-03-30T21:43:24.407 回答