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
Interop! Building a better Backbone.View
Search
RJ Zaworski
September 12, 2014
Technology
0
79
Interop! Building a better Backbone.View
RJ Zaworski
September 12, 2014
Tweet
Share
More Decks by RJ Zaworski
See All by RJ Zaworski
Computing Lessons from the Atomic Age: Complexity, Safety, and Ethics
rjz
0
78
Beyond the Single-Page App: React and the Servers that Serve it
rjz
0
81
Typesafe(ish) React
rjz
1
680
Front-end optimization
rjz
1
450
Technical Interviewing
rjz
0
220
HTTP Security
rjz
2
170
Front-end optimization
rjz
4
260
Other Decks in Technology
See All in Technology
Goに育てられ開発者向けセキュリティ事業を立ち上げた僕が今向き合う、AI × セキュリティの最前線 / Go Conference 2025
flatt_security
0
360
SwiftUIのGeometryReaderとScrollViewを基礎から応用まで学び直す:設計と活用事例
fumiyasac0921
0
150
オープンソースでどこまでできる?フォーマル検証チャレンジ
msyksphinz
0
110
AI ReadyなData PlatformとしてのAutonomous Databaseアップデート
oracle4engineer
PRO
0
220
Adminaで実現するISMS/SOC2運用の効率化 〜 アカウント管理編 〜
shonansurvivors
3
380
大規模サーバーレスAPIの堅牢性・信頼性設計 〜AWSのベストプラクティスから始まる現実的制約との向き合い方〜
maimyyym
2
360
o11yで育てる、強い内製開発組織
_awache
3
120
これがLambdaレス時代のChatOpsだ!実例で学ぶAmazon Q Developerカスタムアクション活用法
iwamot
PRO
4
160
GC25 Recap+: Advancing Go Garbage Collection with Green Tea
logica0419
1
430
AIツールでどこまでデザインを忠実に実装できるのか
oikon48
5
2.4k
KMP の Swift export
kokihirokawa
0
340
多様な事業ドメインのクリエイターへ 価値を届けるための営みについて
massyuu
1
440
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
95
14k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.7k
Optimising Largest Contentful Paint
csswizardry
37
3.4k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Code Review Best Practice
trishagee
72
19k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
It's Worth the Effort
3n
187
28k
Into the Great Unknown - MozCon
thekraken
40
2.1k
GraphQLとの向き合い方2022年版
quramy
49
14k
Raft: Consensus for Rubyists
vanstee
139
7.1k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
Transcript
Interop! Building a better Backbone.View rj zaworski, versal inc. ·
@rjzaworski · github.com/rjz
Let’s Talk Backbone MVC (but mostly “M”) ★ Views: the
DOM ★ Controllers: ?
Let’s Talk Backbone Models are: ★ consistent (RESTful) ★ small
★ event-driven
Let’s Talk Backbone For everything else, frameworks ★ Thorax (templating,
structure, data-binding) ★ Marionette (structure) ★ ...and a cast of thousands
The Goal 1. Composable 2. Transparent 3. Data-driven 4. Portable
Composable Large UIs built of smaller components ★ focused concerns
★ predictable life-cycles
Transparent Both concern and implementation are readily apparent and easy
to follow
Data-driven ★ State lives in the model ★ Views respond
to model changes
Portable Views can be reused ★ outside the host application
★ outside each other ★ outside Backbone
Ex. 1: Backbone Goal: render a <figure> from a Backbone.Model
.
Ex. 1: Backbone Goal: render a <figure> from a Backbone.Model
. var template = _.template([ '<img src="<%- image %>" />', '<figcaption><%- title % ></figcaption>' ].join('')) var FigureView = Backbone.View.extend({ tagName: 'figure', render: function () { var attrs = this.model.toJSON(); this.el.innerHTML = template(attrs); return this; } });
Ex. 1: Backbone Goal: decompose <figure> into an <img> and
a <figcaption>
Ex. 1: Backbone Goal: decompose <figure> into an <img> and
a <figcaption> var Image = Backbone.View.extend({ tagName: 'img', // ... }); var Figcaption = Backbone.View.extend({ tagName: 'figcaption', // ... }); // in parent's render() method this.$el.empty() .append(imageView.render().el) .append(figcaptionView.render().el);
Ex. 1: Backbone ★ manipulate DOM directly ★ what about
old state? var Image = Backbone.View.extend({ tagName: 'img', // ... }); var Figcaption = Backbone.View.extend({ tagName: 'figcaption', // ... }); // in parent's render() method this.$el.empty() .append(imageView.render().el) .append(figcaptionView.render().el);
Ex. 1: Backbone Goal: update <figcaption> when model changes
Ex. 1: Backbone Goal: update <figcaption> when model changes var
Figcaption = Backbone.View.extend({ initialize: function () { this.listenTo( this.model, 'change', this.onModelChange ); }, onModelChange: function () { alert('changed'); this.render(); }, // ...
Ex. 1: Backbone What if we remove the parent view?
var Figure = Backbone.View.extend({ events: { 'click .js-close': 'onCloseClick' }, onCloseClick: function (e) { e.preventDefault(); this.$el.remove(); }, // ... }
Ex. 1: Backbone What if we remove the parent view?
Events stay bound! var Figcaption = Backbone.View.extend({ initialize: function () { this.listenTo( this.model, 'change', this.onModelChange ); }, onModelChange: function () { alert('changed'); this.render(); }, // ...
Back to the goal... 1. Composable? 2. Transparent? 3. Data-driven?
4. Portable?
We can make our lives easier Interop!
React.js ★ UI-centric ★ The “V” in MVC - no
models ★ We don’t need JSX
React.js Advantages ★ One-way data flow ★ Managed lifecycle ★
Immediate mode
Ex. 2: Backbone + React React Children... var ImageView =
React.createClass({ render: function () { return React.DOM.img({ src: this.props.image }); } }); var FigcaptionView = React.createClass({ render: function () { return React.DOM.figcaption(null, this.props.title ); } });
Ex. 2: Backbone + React ...with a Backbone.View parent var
imageEl = $('<div />')[0]; var figcaptionEl = $('<div />')[0]; this.$el.empty() .append(imageEl) .append(figcaptionEl); React.renderComponent( ImageView(this.model.toJSON()), imageEl ); React.renderComponent( FigcaptionView(this.model.toJSON()), figcaptionEl );
Ex. 2: Backbone + React Container <div> aside, ★ Complexity
contained in parent ★ Children are easy to work with! ★ No child zombies
Wire Backbone data to React UI It’s just an “M”
and a “V”: ★ Make friends with toJSON() ★ Keep the interface small
Ex. 3: React Goal: render a (React-powered) <figure> from a
Backbone.Model . var FigureView = React.createClass({ render: function () { return React.DOM.figure({}, [ ImageView(this.props), FigcaptionView(this.props) ]); } }); var props = model.toJSON(); React.renderComponent( new FigureView(props), document.querySelector('.container') );
Ex. 3: React ★ Complexity contained in top-level app ★
All views are easy to work with! ★ No zombies
Ex. 3: React ...and the interface is tiny! var FigureView
= React.createClass({ render: function () { return React.DOM.figure({}, [ ImageView(this.props), FigcaptionView(this.props) ]); } }); var props = model.toJSON(); React.renderComponent( new FigureView(props), document.querySelector('.container') );
Back to the goal... 1. Composable? 2. Transparent? 3. Data-driven?
4. Portable?
Web Components Our simple view fits into the DOM <figure>
<img src="images/milo.jpg" /> <figcaption>Milo</figcaption> </figure>
Web Components What if we could wrap any view up
like this? <figure> <img src="images/milo.jpg" /> <figcaption>Milo</figcaption> </figure> <my-figure title="Milo" image="images/milo.jpg"> </my-figure>
Web Components “...encapsulated and interoperable custom elements that extend HTML
itself” (https://www.polymer-project.org/)
Web Components The bad news: they’re not ready yet ★
Limited native support ★ Implemented via Polymer, X-Tags
Ex. 4: Web Components Register <my-figure> var proto = Object.create(HTMLElement.prototype);
document.registerElement('my-figure', { prototype: proto });
Ex. 4: Web Components proto.createdCallback = function () { var
img = this.img = document.createElement('img'); var shadow = this.createShadowRoot(); shadow.appendChild(img); }; proto.attributeChangedCallback = function (key) { switch (key) { case 'image': this.img.setAttribute('src', this.getAttribute('image')); break; } };
Ex. 4: Web Components Sending in the model... var figure
= document.createElement('my-figure'); figure.setAttribute('image', model.get('image')); $('body').appendChild(figure);
Ex. 4: Web Components Sending in the model... var figure
= document.createElement('my-figure'); figure.setAttribute('image', model.get('image')); $('body').appendChild(figure); <body> <my-figure image="images/milo.jpg"></my-figure> </body>
Ex. 4: Web Components Just like that, we’re back to
the DOM. model.on('change', function () { $('my-figure').attr(model.toJSON()); });
Back to the goal... 1. Composable? 2. Transparent? 3. Data-driven?
4. Portable?
Thank you! rj zaworski · @rjzaworski · github.com/rjz Code samples:
github.com/rjz/backbone-interop