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
56
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
52
Beyond the Single-Page App: React and the Servers that Serve it
rjz
0
62
Typesafe(ish) React
rjz
1
630
Front-end optimization
rjz
1
380
Technical Interviewing
rjz
0
190
HTTP Security
rjz
2
140
Front-end optimization
rjz
4
240
Other Decks in Technology
See All in Technology
ソフトウェア開発における「パーフェクトな意思決定」/Perfect Decision-Making in Software Development
yayoi_dd
2
2.7k
ヤプリQA課題の見える化
gu3
0
150
組織に自動テストを書く文化を根付かせる戦略(2024冬版) / Building Automated Test Culture 2024 Winter Edition
twada
PRO
26
7.1k
新しいスケーリング則と学習理論
taiji_suzuki
9
3.7k
Formal Development of Operating Systems in Rust
riru
1
380
.NET 最新アップデート ~ AI とクラウド時代のアプリモダナイゼーション
chack411
0
150
TypeScript開発にモジュラーモノリスを持ち込む
sansantech
PRO
3
870
株式会社ログラス − エンジニア向け会社説明資料 / Loglass Comapany Deck for Engineer
loglass2019
3
33k
.NET 9 のパフォーマンス改善
nenonaninu
0
2.2k
生成AIによるテスト設計支援プロセスの構築とプロセス内のボトルネック解消の取り組み / 20241220 Suguru Ishii
shift_evolve
0
180
型情報を用いたLintでコード品質を向上させる
sansantech
PRO
2
230
プロダクト組織で取り組むアドベントカレンダー/Advent Calendar in Product Teams
mixplace
0
670
Featured
See All Featured
Designing for humans not robots
tammielis
250
25k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.5k
How to train your dragon (web standard)
notwaldorf
88
5.8k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
49
2.2k
Done Done
chrislema
182
16k
RailsConf 2023
tenderlove
29
960
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Designing on Purpose - Digital PM Summit 2013
jponch
116
7k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
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