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
Philippe CHARRIERE
October 24, 2013
Programming
0
290
Backbone & Marionette avec @xbourguignon à SoftShake
Philippe CHARRIERE
October 24, 2013
Tweet
Share
More Decks by Philippe CHARRIERE
See All by Philippe CHARRIERE
The Plan v3 pour BDX.io
k33g
1
140
Le Plan
k33g
0
140
Prog Fonctionnelle 🐑
k33g
1
340
Apéro fonctionnel
k33g
0
100
Scala Facile
k33g
0
240
Golo, the Tiny Language that gives super powers
k33g
0
76
Golo, the Tiny Language that gives super powers
k33g
0
210
Apéro Fonctionnel
k33g
0
240
Programmation fonctionnelle 🐑 en JS
k33g
2
260
Other Decks in Programming
See All in Programming
OnlineTestConf: Test Automation Friend or Foe
maaretp
0
110
NSOutlineView何もわからん:( 前編 / I Don't Understand About NSOutlineView :( Pt. 1
usagimaru
0
340
受け取る人から提供する人になるということ
little_rubyist
0
250
とにかくAWS GameDay!AWSは世界の共通言語! / Anyway, AWS GameDay! AWS is the world's lingua franca!
seike460
PRO
1
900
エンジニアとして関わる要件と仕様(公開用)
murabayashi
0
300
アジャイルを支えるテストアーキテクチャ設計/Test Architecting for Agile
goyoki
9
3.3k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
1
100
ローコードSaaSのUXを向上させるためのTypeScript
taro28
1
630
Click-free releases & the making of a CLI app
oheyadam
2
120
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
聞き手から登壇者へ: RubyKaigi2024 LTでの初挑戦が 教えてくれた、可能性の星
mikik0
1
130
Jakarta EE meets AI
ivargrimstad
0
220
Featured
See All Featured
Making Projects Easy
brettharned
115
5.9k
Keith and Marios Guide to Fast Websites
keithpitt
409
22k
For a Future-Friendly Web
brad_frost
175
9.4k
Side Projects
sachag
452
42k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
Bash Introduction
62gerente
608
210k
Intergalactic Javascript Robots from Outer Space
tanoku
269
27k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
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