I'm developing a Backbone
application using Marionette
and I need some help to organize the logic in the code.
Currently I have a few views where I handle really similar logic, I want to abstract this to avoid repetition:
View1
onRender: function() {
var pluginData = this.$("selector1").plugin();
var pluginResult = this.handlePluginData(pluginData);
this.doSomethingWithResult1(pluginResult);
}
View2
onRender: function() {
var pluginData = this.$("selector2").plugin();
var pluginResult = this.handlePluginData(pluginData);
this.doSomethingWithResult2(pluginResult);
}
Etc
Note: handlePluginData
do the same thing, doSomethingWithResultN
it's different but can be abstracted with a few params.
So the questions are:
How should I abstract this?, I thought of extending from a BaseView
class and adding the logic there, but I don't know if there's a better way.
It's okay to add a custom Model
class which handles the calculation?. I've been using rails
for a while and I'm used to Model === Table in database.
Thank you very much!
I think Backbone View class is abstract enough. All you have to do is to pass different options when you create new View instance.
And I found that you place the calculating logic in View's render method. Because Backbone is a MVC-based framework, so logic should place in Model and View register event handler which is responsible for rendering layout when Model fire event which view is interested.
In my opinion, you could add a Model which handle calculate and redefine your view.
My simple example:
1.Define a model which is respond for logic calculating:
var MathModel = Backbone.Model.extend({
result: 0,
initialize: function(){
console.log("calculate target: "+this.get("selector"));
console.log("calculate method: "+this.get("method"));
var number = this.handlePluginData();
this.doSomethingWithResult(number);
},
handlePluginData: function(){
return $(this.get("selector")).text();
},
doSomethingWithResult: function(number){
if(this.get("method")==="square"){
this.set({result:(number*number)});
}else{
this.set({result:(number*number*number)});
}
}
});
2.Redefine the View class:
View will register a listener for model "result" data change event and render a initial layout according to the model you assigned.
var AbstractView = Backbone.View.extend({
initialize: function(){
this.listenTo(this.model,"change",this.onModelChange);
this.number = this.model.get("result");
this.render();
},
render: function(){
this.$el.html(this.number);
},
onModelChange: function(model){
this.number = model.get("result");
this.render();
},
plusOne:function(){
this.model.doSomethingWithResult(this.model.handlePluginData());
}
});
3.Pass different options to model when you instantiate a new View.
var view1 = new AbstractView({el:"#result1",model:new MathModel({selector:".square",method:"square"})});
var view2 = new AbstractView({el:"#result2",model:new MathModel({selector:".cubic",method:"cubic"})});
4.HTML:
<div id="select-target">
<span class="square">2</span>
<span class="cubic">2</span>
<button id="plus-one">+1</button>
</div>
<div id="result">
<span id="result1"></span>
<span id="result2"></span>
</div>
5.Plus-one button click event handler:
You could observe how View re-render it's layout when model is changed.
$("#plus-one").click(function(){
$(".square").text(Number($(".square").text())+1);
$(".cubic").text(Number($(".cubic").text())+1);
view1.plusOne();
view2.plusOne();
});
Hope this is helpful for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With