First, I'm the author of JavaScriptMVC, so I'm extremely biased in a whole variety of ways. First, there are 6ish things you will ever do in a JS application:
- Load Scripts
- Respond to user events
- Update the DOM
- Request data from the server
- Convert that data into something useful for JavaScript
- Organize your front-end business logic
Your choice of architecture might depend on what tools you want / need.
For general architecture, I do think it's important to separate concerns.
I strongly encourage you to find some way of doing dependency management, and client side templates. They will make your life a lot easier.
JavaScriptMVC uses a tiered MVC approach that's based heavily around custom UI events and OpenAjax events.
I build my low-level widgets with $.Controller in a similar way to how you would build jQuery widgets. The big difference is that the widgets produce a non-ui event that top level controllers can listen to. For example, a tabs widget might produce a "tab.activate" event like:
$('.tab').trigger('tab.activated')
Then, my higher order controller might listen to tab.activated events, and a the model to update the tab content like:
".flickr tab.activated" : function(tabEl, ev){
Flickr.findAll({type : "rainbows"}, function(images){
tabEl.html("//path/to/view", images );
}
}
Flickr.findAll essentially does a query for flickr messages, then calls back with a list of images. Wrapping the service/ajax functionality with models makes them a lot more reusable.
You'll notice that in the callback I update the html of the tab element with the rendered content from a view. This probably isn't the 'best' way of doing it, but I wanted a quick example. Better would be passing the tabs controller the rendered output, for it to do what it will with it. That way if your tab wants to fade in content someday, it will be able to and your master controller won't have to know about the tab's implementation.
The most important thing is to break down your app into the smallest pieces you can. Have them individually testable (and flexible), and combine the little parts into bigger parts as you work your way up to your application.