Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Backbone & Marionette avec @xbourguignon à Soft...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Philippe CHARRIERE
October 24, 2013
Programming
290
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Backbone & Marionette avec @xbourguignon à SoftShake
Philippe CHARRIERE
October 24, 2013
More Decks by Philippe CHARRIERE
See All by Philippe CHARRIERE
The Plan v3 pour BDX.io
k33g
1
210
Le Plan
k33g
0
220
Prog Fonctionnelle 🐑
k33g
1
400
Apéro fonctionnel
k33g
0
130
Scala Facile
k33g
0
300
Golo, the Tiny Language that gives super powers
k33g
0
140
Golo, the Tiny Language that gives super powers
k33g
0
290
Apéro Fonctionnel
k33g
0
280
Programmation fonctionnelle 🐑 en JS
k33g
2
300
Other Decks in Programming
See All in Programming
5分で問診!Composer セキュリティ健康診断
codmoninc
0
590
SREの積み重ねがAI駆動開発のガードレールになった ― 7つの実践/SRE Guardrails The 7
tomoyakitaura
8
5.4k
ルールを書いて終わらせないハーネスエンジニアリング
yug1224
4
1.7k
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
150
Foundation Models frameworkで画像分析
ryodeveloper
1
140
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
220
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
150
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
550
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
360
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.6k
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
3k
Featured
See All Featured
Deep Space Network (abreviated)
tonyrice
0
230
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
420
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
470
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Mobile First: as difficult as doing things right
swwweet
225
10k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
420
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
620
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Tell your own story through comics
letsgokoyo
1
1k
Optimizing for Happiness
mojombo
378
71k
Transcript
Backbone & Marionette Xavier Bourguignon Philippe Charrière
About Us @k33g_org Lyon Steria Golo Fan #1 @xbourguignon Genève
Hortis GenevaJUG Leader
Backbone.js @k33g_org / Lyon / Steria “tout nu”
1 librairie MVC par Jeremy Ashkenas jQuery + Underscore tous
navigateurs
1 librairie “extra légère” Backbone : 20 kb jQuery :
84 kb Underscore : 14 kb
BB = SPA Helper
Enorme communauté Nombreux plugins “sérieux”
Très simple Code facile à lire facile à “augmenter”
Backbone, c'est Play!> dans votre navigateur
BB est MVC ?
M♥ VC Backbone.Model Backbone.Collection
MVC Templates <%= something %>
MVC Backbone.View ?!*#!??? “la glue”
MVP Backbone.View model view presenter
Mais aussi Backbone.Sync Backbone.Router ...
Modèle Objet
Un modèle "interne"
Pompage var Kind = function() {}; Kind.extend = Backbone.Model.extend;
klass var TinyToon = Kind.extend({ constructor : function (firstName, lastName){
this.firstName = firstName; this.lastName = lastName; }, toString : function() { return this.firstName + " " +this.lastName } }); var babs = new TinyToon("Babs", "Bunny")
héritage var Elmyra = TinyToon.extend({ constructor : function (){ this.firstName
= "Elmyra"; this.lastName = "Duff"; Elmyra.__super__.constructor.call(this); console.log("Oh, it's so cute ♥ ♥ ♥"); }, isChasing : function(toon) { //foo } });
static var Elmyra = TinyToon.extend({ //instance members },{ //statics members
theOnlyOne : null, getInstance : function() { if(Elmyra.theOnlyOne == null) { Elmyra.theOnlyOne = new Elmyra(); } return Elmyra.theOnlyOne; } }); var elmyra = Elmyra.getInstance();
Backbone.Model Backbone.Collection Backbone.sync
var Player = Backbone.Model.extend({ urlRoot:"/players" }); var bob = new
Player({ firstName : "Bob", lastName : "Morane" }) Model
get() / set() bob.get("firstName") bob.set("firstName","Bob") bob.set({ lastName:"Morane", twitter:"@bobby" }) bob.on(
"change:lastName change:firstName", ...);
mais aussi save() fetch() destroy()
Backbone.sync Appelé à chaque lecture / écriture des modèles
Backbone.sync Par défaut : REST $.ajax()
bob.save() POST : http://domain/players save
var bob = new Player({ id:"001" }) bob.fetch() GET :
http://domain/players/001 fetch
bob.set("twitter","@bobby") bob.save() PUT : http://domain/players/001 save/update
bob.destroy() DELETE : http://domain/players/001 destroy
var Players = Backbone.Collection. extend({ url :"/players", model : Player
}); var players = new Players() Collection
players.fetch() GET : http://domain/players/ fetch : getAll
_.template()
<ol> <% _.each(players, function(player) { %> <li id="<%= player.id %>">
<%= player.firstName %> <%= player.lastName %> </li> <% }); %> </ol> Avec Underscore template
d'autres moteurs Mustache Handelbars TempoJS ...
Backbone.View Controller Presenter
var PlayersView = Backbone.View.extend({ el : "#players", initialize : function()
{ this.template = _.template($("#template").html()); }, render : function() { this.$el.html( this.template({ players:this.collection.toJSON() }) ); } });
var PlayersView = Backbone.View.extend({ /*...*/ events:{ "click :checkbox" : function(event)
{}, "click .btn-success" : function() {} } }); var playersView = new PlayersView({collection:players})
Backbone.Router
var router = Backbone.Router.extend({ routes: { "home": "index", "products/:computer": "display",
"products/:computer/:model": "display" }, index: function() { }, display: function(computer, model) { } });
1 Exemple simple 1 “blog”
Vue
Vue Modèles & Collections
Vue Modèles & Collections Contrôleur
Vue Modèles & Collections Contrôleur Go!
\o/
Plus loin: -> + commentaires
None
None
None
None
None
None
nouvelle version
Donc pas mal de code en plus, et ce n’est
pas fini ...
Memory leaks
None
None
None
Conclusion
BB != machine à tout faire
Marionette.js @xbourguigon / Genève / Hortis Make your Backbone application
dance !
1 librairie par Derick Bailey Pour aller encore plus loin
avec Backbone
Marionette = SPA with BB Helper
ItemView
MyItemView = Marionette.ItemView.extend({ template:"#my-view-template" }); var myView = new MyItemView({
model: someBBModel });
CollectionView
ItemsView = Marionette.CollectionView.extend({ itemView:MyItemView }); var myCollectionView = new ItemsView({
collection: someBBCollection });
Region
var mainRegion = new Marionette.Region({ el:"#main-container" }); var view =
new MyView(); mainRegion.show(view); var otherView = new AnotherView(); mainRegion.show(otherView);
Layout
(wrapper template) #someRegion #anotherRegion
var MyLayout = Marionette.Layout.extend({ template:"#my-layout-template", regions:{ region1:"#someRegion", region2:"#anotherRegion" } });
var layout = new MyLayout(); mainRegion.show(layout); layout.region1.show(new SomeView()); layout.region2.show(new OtherView());
Autres raffinements pour les vues
var itemView = new MyView({model: someModel}); itemView.render(); var collectionView =
newOtherView({ collection: someCollection }); collectionView.render(); automatic render
mainRegion.show(layout); layout.region1.show(new SomeView()); layout.region2.show(new OtherView()); layout.region1.show(new ThirdView()); mainRegion.show(anotherLayout); zombie killing
var myView = Marionette.ItemView.extend({ template:"#my-view-template", ui:{ mainButton: "#mainButton" }, clickButton:
function() { this.ui.mainButton.click(); } }); ui objects
var myView = Marionette.ItemView.extend({ template:"#my-view-template", modelEvents:{ "change:name":"doThing" }, doThing: function()
{ // call when the name changes ! } }); model events
var myView = Marionette.CollectionView.extend({ template:"#my-view-template", collectionEvents:{ "add":"itemAdded" }, itemAdded: function()
{ // call when the name changes ! } }); collection events
Marionette === scalable BB
None
App Sub-App Sub-App Sub-App
Découpage en modules
Application
(function(global) { var MyApp = new Marionette.Application(); MyApp.addRegions({ mainRegion:"#main" });
MyApp.on("initialize.after", function() { Backbone.history.start(); }) global.MyApp = MyApp; })(window)
<script src="/js/app.js" /> <script src="/js/itemView.js" /> <script> $(function(){ MyApp.start(); });
</script>
Module
MyApp.module("myModule", function(Mod, App, BB, Marionette, $, ...) { var SomeModel
= Backbone.Model.extend({...}); var ItemView = Marionette.ItemView.extend ({...}); var model = new SomeModel(); ...
… Mod.initializer(function() { var promise = model.fetch(); $.when(promise).then(function(){ var view
= new SomeView(); MyApp.mainRegion.show(view); }); }); });
MyApp.module("SubApp", function() { this.startWithParent = false; this.addInitializer(function() {...}) } MyApp.module("SubApp").start();
MyApp.module("myModule").stop(); start / stop
Controller
WTF ?
Mediator All purpose object Public API for component controller
var ThatThing = Marionette.Controller.extend({ doStuff: function() { ... } });
Blog Marionette version
Questions ?
On a plus le temps :-(
Merci
@k33g_org @xbourguignon