5
votes

I use backbone in most of my projects, and I think I know exactly what the M V C means: M for abstract of the data, V for representation and C for handlers.

However during my current project I found that there are a lot of views interactive with each other, while there are little modes(data with the server).

For example, I have there complex view named V1 V2 V3, when user do something in the V1, V2 should respond accordingly, so does the V3 and etc, and at the last step, a requst may be made to request data from the server. And most of the request are used to fetch data rather than modify data.

It does not like the common style: one(or more) view for one model such as the CRUD operation.

Now I have two ideas:

1 Virtual model

Create a backbone model to represent the state of the whole application, bind this model to all the views. Sounds like make the application as a state machine.

While it is not easy to describe the application with different states.

2 Use the event mediator

Use the event mediator to register/un-register different events, then the views can trigger or respond by different events.

While how to define the events to avoid insufficien or excessive, in a word to make the events orthogonal is not easy. Or I have not found any instructions yet.

Is there any other alternative solutions?

3
interactive with each other do you mean that you display these views together and want them updated at the same time? - edoput

3 Answers

4
votes

I think that it is a quite relevant question actually.

Create a backbone model to represent the state of the whole application, bind this model to all the views. Sounds like make the application as a state machine.

This doesn't seem like a very good idea, if the model isn't a consistent representation that corresponds to a specific backend resource.
Ideally, a view is a representation of a single model or collection. When a view would be bound to a model with unrelated properties, this doesn't seem too practical to manage in all circumstances, also due to an unforseeable future.

Use the event mediator to register/un-register different events, then the views can trigger or respond by different events.

I don't think that it is overall a good idea to make views respond to custom events but this is personal for me. When apps become larger, assigning too much responsibility to complex views can become a mess; therefore I take it as a general rule to limit the task of the view to:

  • Rendering templates;
  • Activating plugins (if they're specific to the view);
  • DOM event binding;
  • (Model binding);
  • Methods internal to the view (related to the DOM);
  • Triggering custom events to notify other listeners when further action is required after interaction with the view;

In any case, in my experience I've found that it is practical to use a custom presenter/controller to instantiate / update views on custom events, and not let the view itself worry about these things at all. It keeps them clean and you always know what you will find there.

The views 1, 2 and 3 as you mention can be re-rendered from the presenters.
The presenter does something like:

"I get some data from a service and give it to some of my views that require them. If something changes, I'll let them know"

I usually have 1 presenter per related set of views.

I like this approach because:

  • It keeps logic for related views centralised;
  • When an event is triggered, the presenter needs to listen only once for all the views that it controls;
  • Presenters are given the authority to talk to each other, which is to my feeling easier to control than when all views would start talking to each other through each other;

In simple cases, all of this doesn't matter too much probably. But when building a larger application, I found that it can become a mess.

My two cents

1
votes

I have there complex view named V1 V2 V3, when user do something in the V1, V2 should respond accordingly, so does the V3 and etc

It doesn't seem like you have 3 views, but in fact 1 view with 3 interrelated sections. I would use one super view that renders 3 child views, and listen to view events. For example:

Backbone.View.extend({
  initialize: function () {
    this.v1 = ...;
    this.v2 = ...;
    this.v3 = ...;

    this.v1.on('user do something', this.v2.respondAccordingly);
    this.v1.on('user do something', this.v3.soDoesEtc);
  }
})

And in view 1:

$('button').on('click', function () {
  self.trigger('user do something');
})
0
votes

This is a problem that many Backbone developers face.

What I've done in the past is to have a baseModel/baseCollection, and treat them as an abstract class/interface from which other models/collections extend, respectfully. These base objects would contain a listener/trigger methods which I could then use across my application to have changes in one model/collection be able to initiate updates on collections/models (thus triggering view changes) respectively as I chose. Using this method allowed me to compose my application by having the appropriate objects listen/broadcast events appropriately as I wished.

One of my friends created a server-side JS state machine which would initiate super-models (app-level model which in turn could trigger sub-view model/collection updates).

Of course, Marionette provides a framework that makes this a little less manual and allows you to get back to writing app-code.

One of the joys and burdens of Backbone.js is that you have all the flexibility you want. :)