Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
既存プロダクトのViewをReactに置き換える
Search
boiyama
December 15, 2016
Programming
2.3k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
既存プロダクトのViewをReactに置き換える
【ヒカ☆ラボ】最新フロントエンドフレームワークを利用した開発事例!
https://atnd.org/events/83403
用の資料です
boiyama
December 15, 2016
More Decks by boiyama
See All by boiyama
Reproのビジネスサイドを支えるJS
boiyama
0
200
バックオフィスに行ったソフトウェアエンジニアの業務効率化事例
boiyama
1
300
2018年、IE6対応サイトを作る
boiyama
4
1k
ヤバいESLint/TSLintルール作っちゃったかもしれない
boiyama
0
1.5k
チームをCQRS
boiyama
1
1.7k
フロントエンドのサーバーレス SSR編
boiyama
0
730
Serverless for Front-end Server-Side Rendering
boiyama
1
150
Learning Elm in JS
boiyama
1
580
JSでElmを学ぶ
boiyama
0
120
Other Decks in Programming
See All in Programming
Modernizing iOS Apps
seyfoyun
0
130
最近”作らせてる” ローカルAIアプリの話
akit37
0
520
Next.js: The final boss of Web Performance
guaca
0
360
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
6
2k
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
12
11k
Web Framework Benchmark Battle 2026, Any%
a_matsuda
3
3.1k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
240
気持ちぃ〜角丸 Squircle
ryu1013
0
370
조합이폭발하는디자인시스템이걸눈으로도테스트하라고요
giljongyu
0
650
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
170
Event is what happens
moro
2
2.1k
ActionController meets Protocol Buffers
sorah
1
750
Featured
See All Featured
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
59k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
720
4 Signs Your Business is Dying
shpigford
187
23k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
500
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
230
Abbi's Birthday
coloredviolet
4
11k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
The browser strikes back
jonoalderson
0
1.9k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Google's AI Overviews - The New Search
badams
0
1.6k
Transcript
طଘϓϩμΫτͷViewΛ Reactʹஔ͖͑Δ Dec 15 2016 @boiyaa
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ϓϩϑΟʔϧ ▸ @boiyaa ▸ 33ࡀ ▸ ϑϧεέοϕΤϯδχΞ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ͢͜ͱɾ͞ͳ͍͜ͱ ▸ ͢͜ͱ ▸ طଘϓϩμΫτʹReactΛಋೖ͢Δ͜ͱʹͨ͠എܠ ▸ ࣮αϯϓϧ ▸ https://github.com/boiyaa/todomvc-backbone-react
▸ ͞ͳ͍͜ͱ ▸ πʔϧͱ͔ES6ͱ͔ͷৄ͍͠༰
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ࣮ݱࡏ ▸ View͚ͩஔ͖͑ΔͷΊ͍ͯ·͢ʢٕज़తෛ࠴తͳཧ ༝Ͱʣ ▸ ͜ͷεϥΠυͰɺViewΛReactʹஔ͖͑Α͏ͱࢼߦࡨޡ ͍ͯͨ࣌͠ͷ͓Λ͠·͢
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ৽ٕज़Λݕ౼ͨ͠എܠ ▸ 4લʹ࡞ΒΕͨۀγεςϜ ▸ ϑϩϯτΤϯυFWʹBackbone.jsΛ࠾༻ ▸ ػೳͷܧ͗͠Λ܁Γฦ͍ͯͬͨ݁͠ՌɺDOMૢ࡞ͷॲཧ͕ᷓΕ͔͑ͬͨ Backbone ViewʹͳΔ
▸ ͏গ͠εϚʔτʹUIΛ࡞ΕΔํ๏ʹม͑ΔͨΊɺjQueryʹґଘ͠ͳ͍React ͱAngular2͕ީิʹ্͕Δ ▸ Ͱ͖Εطଘࢿ࢈׆༻͍ͨ͠ͱ͍͏͜ͱͰɺUI·ΘΓͷΈΛReactʹஔ͖ ͑ΔํࣜͱɺAngular2Ͱ1͔Β࡞Γ͢ํࣜͷ̎௨Γݕ౼͢Δ͜ͱʹͳͬͨ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ࣌ͷݕূ༰ ▸ ̍൪ӈͷ߲͍͍ͬͨͳΜͩͱ͍͏ײ͡Ͱ͕͢ɺݱߦʹͦ͏͍͏ը໘͕͋Γɺ ສݸͷDOMͷඳըૢ࡞ʹ͕͔͔࣌ؒΔΑ͏ͩͱଞ߲͕ັྗతͰ࠾༻Ͱ ͖ͳ͍ͱ͍͏͜ͱͰ༻ҙ͞Ε߲ͨͰ͢ɻʢWhy?ʣ ▸ ݁ՌɺAngular2མબ͠ɺBackboneͷΈͷը໘ͱBackbone + Reactͷը໘Λ
͍͚͍ͯ͘ͱ͍͏͜ͱʹͳΓ·ͨ͠ ֶशίετ ੜ࢈ੑ อकੑ طଘࢿ࢈׆༻ ̍ສߦදૢ࡞ ύϑΥʔϚϯε Backbone ˕ ̋ ˚ ˕ ̋ Backbone + React ̋ ˕ ̋ ̋ ˚ Angular2 ˚ ˕ ̋ × ˚
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Reactʹ͍ͭͯ ▸ MV*Ͱ͍͏ViewͷΈఏڙ͢ΔϑϨʔϜϫʔΫ ▸ React͚ͩͳΒ֮͑Δ͜ͱগͳ͍Ͱ͢ ▸ React ComponentΫϥεΛܧঝ͠ɺHTML, CSS,
JSͷͻͱ͔ͨ·ΓΛఆٛͨ͠ίϯ ϙʔωϯτΛ࡞Δͷ͕جຊతͳ͍ํͰ͢ɻ ▸ ίϯϙʔωϯτɺJSXͱ͍͏จ๏ΛͬͯHTMLͷΑ͏ʹݺͼग़͠·͢ʢྫɿ <Example hoge=“fuga” />ʣ ▸ ίϯϙʔωϯτʹͨ͠propsɺίϯϙʔωϯτ͕࣋ͭstateʹೖΓɺͦΕ Βͷ͕ߋ৽͞ΕΔͱίϯϙʔωϯτ͕࠶ඳը͞Ε·͢ ▸ Πϕϯτॲཧλάଐੑʹઃఆ͠·͢ʢྫɿ<Example onClick={handleClick} />ʣ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Backboneʹ͍ͭͯ ▸ RESTful APIͱͷ࿈ܞΛγϯϓϧʹநԽɻେ͖̏ͭ͘ͷػೳΛ࣋ͪ·͢ ▸ Model: APIͷ୯Ϧιʔεͱಉظ ▸ Collection:
Modelͷू߹ͰɺAPIͷෳϦιʔεͱಉظ ▸ View: ඥͮ͘ModelCollectionͷσʔλΛDOMʹө͠ɺDOMͷϢʔβೖྗ ΛModelCollectionʹө
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ReactԽ Part.1 : ΊͪΌΊͪΌബ͘ReactΛ͏ ▸ Ұ൪؆୯ͳ͍ํͰ͢ɻ ؆୯ʹಋೖͰ͖·͕͢ɺ͜ͷ͍ํͰReact͍͍ͨਓ͍ͳ͍ͱ ࢥ͏ͷͰɺࢀߟఔʹհ͠·͢ ▸
ࢀߟURL ▸ https://facebook.github.io/react/docs/installation.html#using-a-cdn ▸ https://facebook.github.io/react/docs/react-without-es6.html ▸ https://facebook.github.io/react/docs/react-without-jsx.html ▸ ຊདྷReactɺYarn,npmͷύοέʔδϚωʔδϟɺwebpack,Browserifyͷόϯυϥɺ BabelͷίϯύΠϥΛซͤͯ׆༻͢Δ͜ͱΛਪ͍ͯ͠·͕͢ɺࠓճͦΕΒͷπʔϧ ΛΘͣ͏ํ๏Ͱ͢
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Α͋͘ΔBackboneϓϩδΣΫτͷྫ ▸ htmlʹςϯϓϨʔτΛॻ͍ͯɺ <script type="text/template" id="item-template"> <div class="view"> <input
class="toggle" type="checkbox" <%= completed ? 'checked' : '' %>> <label><%- title %></label> <button class="destroy"></button> </div> <input class="edit" value="<%- title %>"> </script>
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Α͋͘ΔBackboneϓϩδΣΫτͷྫ ▸ BackboneViewͰɺUnderscoreͱjQueryͰඳը͠·͢Ͷ template: _.template($('#item-template').html()), render: function () {
this.$el.html(this.template(this.model.toJSON())); },
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ htmlʹCDNͷReactΛه͠ɺ <script src="https://unpkg.com/react@15/dist/react.js"></ script> <script src="https://unpkg.com/react-dom@15/dist/react- dom.js"></script>
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ htmlͷςϯϓϨʔτΛফͯ͠ɺReact ComponentΛ࡞Γ·͢ var Item = React.createClass({ render:
function() { return React.createElement('div', null, React.createElement('div', {className: 'view'}, React.createElement('input', { className: ‘toggle', type: ‘checkbox', checked: this.props.completed }, null), React.createElement('label', null, this.props.title), React.createElement('button', {className: 'destroy'}, null) ), React.createElement('input', { className: ‘edit', defaultValue: this.props.title }, null) ); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ BackboneViewͷඳը͢Δͱ͜ΖΛॻ͖͑·͢ render: function () { ReactDOM.render( React.createElement(Item,
this.model.toJSON(), null), this.$el.get(0) ); },
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ <script type="text/template" id="item-template"> <div class="view"> <input class="toggle" type="checkbox" <%=
completed ? 'checked' : '' %>> <label><%- title %></label> <button class="destroy"></button> </div> <input class="edit" value="<%- title %>"> </script> var Item = React.createClass({ render: function() { return React.createElement('div', null, React.createElement('div', {className: 'view'}, React.createElement('input', { className: ‘toggle', type: ‘checkbox', checked: this.props.completed }, null), React.createElement('label', null, this.props.title), React.createElement('button', {className: 'destroy'}, null) ), React.createElement('input', { className: ‘edit', defaultValue: this.props.title }, null) ); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ template: _.template($('#item-template').html()), render: function () { this.$el.html(this.template(this.model.toJSON())); }, render:
function () { ReactDOM.render( React.createElement(Item, this.model.toJSON(), null), this.$el.get(0) ); },
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part.1 ·ͱΊ ▸ ͱͯݟͮΒͯ͘ݏͰ͢Ͷɻ ▸ ReactͬΆ͞ΛࣺͯΕɺಋೖࣗମ؆୯ʹͰ͖Δͱ͍͏ྫ Ͱͨ͠
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ReactԽ Part.2 : JSXͰBackbone TemplateΛஔ͖͑Δ ▸ ύοέʔδϚωʔδϟɺόϯυϥɺίϯύΠϥΛಋೖ͢Δ͜ͱʹͳΓ·͕͢ɺ ReactࣗମͰ֮ ͑Δ͜ͱগͳ͍͍ํͰ͢ɻ
πʔϧʹ׳Ε͍ͯͳ͚Εɺ࿅शʹͪΐ͏Ͳ͍͍͘Β͍ͷม ߋྔͰ͠ΐ͏ɻ ▸ ࢀߟURL ▸ https://nodejs.org/en/download/package-manager/ ▸ https://yarnpkg.com/en/docs/install#alternatives-tab ▸ https://facebook.github.io/react/docs/installation.html#installing-react ▸ https://webpack.js.org/guides/installation/ ▸ https://babeljs.io/docs/setup/#installation ▸ https://facebook.github.io/react/docs/introducing-jsx.html
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ඞཁͳͷΛΠϯετʔϧ͢Δ ▸ ύοέʔδϚωʔδϟYarnΛΠϯετʔϧ ▸ ύοέʔδϚωʔδϟͱ͍͑npmͰ͕͢ɺReactؔ࿈ͷυΩϡϝϯτͰyarnϕʔ εͰॻ͔Ε͍ͯΔ͜ͱ͕ଟ͍ͷͰࠓճͪ͜ΒΛ͍·͢ɻ ▸ ίϚϯυେମޓ͍ͯ͠ΔͷͰɺnpm͕͍͍ํదٓஔ͖͑ͯಡΜͰ͍ͩ͘͞ɻ ▸
npmίϚϯυରরදɿ https://yarnpkg.com/en/docs/migrating-from-npm ▸ YarnΛͬͯɺReactͱɺόϯυϥʹwebpackɺίϯύΠϥʹbabelΛΠϯετʔϧ yarn add react react-dom yarn add webpack babel-core babel-loader babel-preset-react --dev
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ React ComponentΛ࡞ͬͯΈ·͢ ▸ ҰݟHTMLʹݟ͑Δ͜ͷจ๏͕JSXͰ͢ɻ className, defaultValueগ͠HTMLͱ ҧ͏ଐੑ͕͋Γ·͢Ͷɻ
var Item = React.createClass({ render: function() { return ( <div> <div className="view"> <input className="toggle" type="checkbox" checked={this.props.checked} /> <label>{this.props.title}</label> <button className="destroy"></button> </div> <input className="edit" defaultValue={this.props.title} /> </div> ); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ BackboneViewͷඳը͢Δͱ͜ΖΛॻ͖͑ͯΈ·͢ render: function () { ReactDOM.render( <Item
title={this.model.get('title')} checked={this.model.get('completed')} />, this.$el.get(0) ); },
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ <script type="text/template" id="item-template"> <div class="view"> <input class="toggle" type="checkbox" <%=
completed ? 'checked' : '' %>> <label><%- title %></label> <button class="destroy"></button> </div> <input class="edit" value="<%- title %>"> </script> var Item = React.createClass({ render: function() { return ( <div> <div className="view"> <input className="toggle" type="checkbox" checked={this.props.checked} /> <label>{this.props.title}</label> <button className="destroy"></button> </div> <input className="edit" defaultValue={this.props.title} /> </div> ); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ template: _.template($('#item-template').html()), render: function () { this.$el.html(this.template(this.model.toJSON())); }, render:
function () { ReactDOM.render( <Item title={this.model.get('title')} checked={this.model.get('completed')} />, this.$el.get(0) ); },
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ ςϯϓϨʔτ෦ࣅͨΑ͏ʹهड़Ͱ͖ΔΑ͏ʹͳΓɺඳ ը෦͕ײతͳදݱʹͳΓ·ͨ͠Ͷ ▸ ͨͩ͠ɺ͔͜͜ΒϏϧυ͢Δ࡞ۀ͕ඞཁͰ͢
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ webpack.config.jsΛ࡞ΓɺϏϧυઃఆΛॻ͖·͢ module.exports = { entry: { 'components/Item.js':
'./js/components/Item.js', 'views/todo-view.js': './js/views/todo-view.js' }, output: { path: `${__dirname}/dist`, filename: '[name]' }, module: { loaders: [ { test: /\.js$/, loader: 'babel', query: { presets: ['react'] }
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ package.jsonʹϏϧυεΫϦϓτΛه͠·͢ "scripts": { "build": "webpack" },
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ Ϗϧυ͠·͠ΐ͏ ▸ ͜ΕͰdistʹϏϧυͨ͠jsϑΝΠϧ͕ੜ͞ΕΔͷͰɺ͜ΕΛhtmlʹಡΈ ࠐ·ͤ·͢ yarn run build
<script src="node_modules/react/dist/react.js"></script> <script src="node_modules/react-dom/dist/react-dom.js"></ script> <script src="dist/components/Item.js"></script> <script src="dist/views/todo-view.js"></script>
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ςϯϓϨʔτΛReactԽ͢Δ ▸ ϑΝΠϧ͕Ͱ͖ΔͨΊɺϖʔδؒͰͷςϯϓϨʔτͷڞ༗͕༰қʹ ▸ ͨͩɺςϯϓϨʔτϑΝΠϧΓग़͚ͩ͠Ͱ͋ΕɺUnderscore TemplateͰJSTίϯύΠϥΛ࣮͑ݱͰ͖·͢ɻ ▸ ͦΕ͚ͩͩͱ͍ͨͨ͠ϝϦοτʹͳΓ·ͤΜͶ ▸
JSXͷ͞Βʹ͍͍ͱ͜ΖɺJSXͰReact ComponentΛݺͼग़͢͜ͱ ͕Ͱ͖ΔͷͰɺΑΓݟ͘͢ίϯϙʔωϯτͷೖΕࢠΛදݱͰ͖Δͱ ͜ΖͰ͢
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Underscore Templateͷ߹ ▸ ཁૉʹࢠཁૉΛՃ͢ΔͳΒɺView͔ΒViewΛݺͼग़ͯ͠ɺ DOMʹૠೖ͢ΔॲཧΛॻ͘͜ͱʹͳΓ·͢ ▸ html <script type="text/template"
id="parent"> <div class="parent"></div> </script> <script type="text/template" id="child"> <div class="child"><%- text %></div> </script>
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Underscore Templateͷ߹ ▸ js var ChildView = Backbone.View.extend({ template:
_.template($('#child').html()), render: function () { this.$el.html(this.template(this.model.toJSON())); } }); var ParentView = Backbone.View.extend({ template: _.template($('#parent').html()), render: function () { this.$el.html(this.template()); var parent = this.$el.find('.parent'); this.collection.each(function (model) { var child = new ChildView({model: model}); parent.append(child.$el); }); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Reactͷ߹ ▸ ίϯϙʔωϯτ͔ΒίϯϙʔωϯτΛݺͼग़ͤ·͢ var Parent = React.createClass({ render: function()
{ var children = []; this.props.collection.each(function (model) { children.push(<Child model={model}>); }); return <div className="parent">{children}</div>; } }); var Child = React.createClass({ render: function() { return <div className="child">{this.props.text}</div>; } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Reactͷ߹ ▸ ͳͷͰView1ͭʹͳΓ·͢ var ParentView = Backbone.View.extend({ render: function
() { ReactDOM.render( <Item collection={this.collection} />, this.$el.get(0) ); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part.2 ·ͱΊ ▸ ͜ͷΑ͏ʹγϯϓϧʹهड़Ͱ͖ɺؾܰʹڞ௨UI෦Λͯ͠͠·͑·͢ɻ Child͕ඳըͷΈͰ͍͍߹ɺ͜ͷख๏ͰऔΓೖΕΔͷ͋Γͩͱࢥ͍·͢ɻ ▸ ͔͠͠ͳ͕Βɺ Childʹੜ࣌Ϣʔβೖྗ࣌ͷΠϕϯτॲཧΛ࣋ͨͤͯɺͦΕڞ௨Խ͍ͨ͠ ͱ͍͏߹ɺ
React ComponentͰͦ͏͍ͬͨࣄॻ͚·͕͢ɺͷʹΑͬͯBackbone View ʹॻ͍ͯ͋ͬͨΓReact Componentʹॻ͍ͯ͋ͬͨΓ͢ΔͱɺՄಡੑอकੑ ΛԼ͛ͯ͠·͏ͷͰɺ ݁ہChildͷBackbone ViewΛ࡞ͬͯParentView͔Βݺͼग़͢͜ͱʹͳΓ·͢ɻ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ReactԽ Part.3 : Backbone ViewΛReact Componentʹஔ͖͑Δ ▸ React ComponentͷػೳͰBackbone
ViewͰ͍ͬͯΔ͜ͱΛҠ২͠·͢ɻ ▸ มߋྔ݁ߏ͋ΓɺES2015+Λಋೖ͠JSͷॻ͖ํ͕݁ߏมΘΓ·͕͢ɺ Backboneʹͳ͍ViewͷՄಡੑɾอकੑ্ͷͨΊͷ༷ʑͳϝϦοτΛڗ डͰ͖·͢ɻ ▸ ࢀߟURL ▸ https://facebook.github.io/react/docs/components-and-props.html ▸ https://facebook.github.io/react/docs/handling-events.html
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Α͋͘ΔBackbone View var View = Backbone.View.extend({ tagName: 'li', //
ユーザ入力イベントとハンドラの紐付け events: { 'click .toggle': 'toggleCompleted' }, // モデル変更イベントとハンドラの紐付け initialize: function () { this.listenTo(this.model, 'change', this.render); }, render: function () { this.$el.html(this.template(this.model.toJSON())); }, toggleCompleted: function () { this.model.toggle(); } });
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ React ComponentԽ // 依存ライブラリの参照はHTMLではなくjsに書く import Item, {Component} from 'react';
// classが使える class Todo extends Component { // 描画後イベント componentDidMount() { // モデル変更イベントとハンドラの紐付け this.props.model.on('change', this.handleChangeModel); } handleChangeModel() { // 描画実行 this.forceUpdate(); } handleClickToggle() { this.props.model.toggle(); } 〜つづく〜
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ React ComponentԽ 〜つづき〜 render() { const title = this.props.model.get('title');
const completed = this.props.model.get('completed'); // ユーザ入力イベントとハンドラの紐付け return ( <li> <div className="view"> <input className="toggle" type="checkbox" checked={completed} onClick={this.handleClickToggle} /> <label>{title}</label> </div> </li> ); } }
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ React ComponentԽ ▸ BackboneɺϚʔΫΞοϓͱJSΛ͠·͕͢ɺReactɺ݁߹͠·͢ɻ HTMLίʔσΟϯά͔͠Ͱ͖ͳ͍ਓͱɺϓϩάϥϚͷۀͰ͍ͬͯΔνʔϜͩͱෆ͖ʁ ▸ খ͘͞࡞ΒΕͨίϯϙʔωϯτɺ ΠϕϯτͷྲྀΕ͕ಡΈ͘͢ɺίʔυ͕ࢄ͍ͯ͠ͳ͍ͷͰɺ ࠶ར༻࣌ʹؾʹ͔͚Δ෦ݮΓ·͢ɻ
▸ ·ͨ෦Ͱఆٛ͞ΕͨϝιουCSSΫϥεӅṭ͞Εɺ ֎͔Βࢀর͢Δ͜ͱ͕Ͱ͖ͳ͍ͷͰɺ໊લͷڝ߹ͰࠔΔ͜ͱ͕ͳ͘ͳΔɺ ϝϦοτ͕͋Γ·͢ɻ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ React ComponentԽ ▸ htmlʹࢀরΛه͢Δࡍɺ webpackʹΑͬͯɺimportઌͷϑΝΠϧΛશͯΤϯτϦʔϑΝ Πϧʹ݁߹͞Ε͍ͯΔͷͰɺಡΈࠐΉͷ1ͭͰΑ͘ͳΓ·͢ <script src="dist/views/app-view.js"></script>
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part.3 ·ͱΊ ▸ Backbone ViewͰΓʹ͍͘ίϯϙʔωϯτࢦΛ༰қ ʹͰ͖·ͨ͠ ▸ UIͷΈίϯϙʔωϯτͷೖΕࢠ͚ͩͰͳ͘ɺ ςϯϓϨʔτ͚ͩͷReactԽͷ՝ͱͳΔɺػೳͷ͋Δίϯ
ϙʔωϯτͷڞ༗ɺ Backbone View͝ͱReact Componentʹஔ͖͑Δ͜ͱͰ ࣮ݱͰ͖·ͨ͠
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ReactԽ Part.4 : ComponentΛׂͰׂ͠ɺ࠶ར༻ੑΛߴΊΔ ▸ Part3ͰɺϩδοΫͷ͋ΔComponent෦Ͱঢ়ଶૢ࡞Λߦ͍ͬͯΔ ͨΊɺ ෦༻ͷঢ়ଶϓϩύςΟstateΛ༻͍ͯ͠·͢ɻ ▸
͔͠͠ͳ͕ΒɺComponentεςʔτϨεʹ࡞ΒΕ͍ͯΔํ͕ɺ Մಡੑɾ࠶ར༻ੑɾςελϏϦςΟ্͕͠·͢
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Componentͷׂ ▸ ReactΛ༻͢ΔFWͷFlux UtilsReduxͰɺ ComponentΛ2ׂͭͰׂ͢Δ͜ͱΛਪ͍ͯ͠·͢ɻ ▸ 1ͭɺ͞ΕΔpropsʹԠͯ͡UIΛඳը͢ΔεςʔτϨείϯϙʔωϯτ ͏1ͭɺσʔλͱViewΛૢ࡞͢Δίϯϙʔωϯτ
લऀViews·ͨPresentational Componentsɺ ޙऀContainers·ͨContainer ComponentsͱݺΕ·͢ ▸ ࢀߟURL ▸ https://facebook.github.io/flux/docs/flux-utils.html#best-practices ▸ http://redux.js.org/docs/basics/UsageWithReact.html#presentational-and- container-components
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part3ͷComponentΛViewͱContainerʹׂ͢Δ ▸ View ▸ propsΛඳը͢Δ͚ͩ ͳͷͰFunctional Componentʹ͠·͢ ▸ https://
facebook.github.io/ react/docs/ components-and- props.html#functional- and-class-components const Item = (props) => { // 状態は外から渡される const {title, checkedToggle} = props; const handleClickToggle = () => { // 外から渡されたハンドラにそのまま返す props.onClickToggle(); } return ( <li> <div className="view"> <input className="toggle" type="checkbox" checked={checkedToggle} onClick={handleClickToggle} /> <label>{title}</label> </div> </li> ); }
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part3ͷComponentΛViewͱContainerʹׂ͢Δ ▸ Container class ItemContainer extends Component { componentDidMount()
{ this.props.model.on('change', this.handleChangeModel); } handleChangeModel() { this.forceUpdate(); } handleClickToggle() { this.state.model.toggle(); } render() { const title = this.props.model.get('title'); const completed = this.props.model.get('completed'); // Itemの状態はこちらで管理する return ( <Item title={title} checkedToggle={completed} onClickToggle={handleClickToggle} /> ); } }
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part.4 ·ͱΊ ▸ σʔλͷΓͱΓͱɺUIͷදݱ͕ผΕͨ͜ͱͰɺ ͞ΒʹUIͷ࠶ར༻ੑ্͕ͨ͠ͱࢥ͍·͢ɻ ▸ ྫ͑ɺDate PickerͷΑ͏ͳϢʔβೖྗUIɺ ೖྗʹΑͬͯͲ͏ॲཧ͢Δ͔ɺ͏ॴͰܾΊ͍ͨͷͳͷ
Ͱɺ͜ͷϓϥΫςΟε͕༗ޮʹಇ͖·͢ɻ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ReactԽ Part.5 : σʔλϑϩʔʹFluxΛऔΓೖΕΔ ▸ FluxFacebook͕ఏএ͢Δ୯ํσʔλϑϩʔΞʔΩςΫνϟ ▸ Model-ViewͰModel͕σʔλͱσʔλʹର͢ΔཁٻΛ͍࣋ͬͯ·͕͢ɺ FluxͰɺσʔλ(Store)ͱσʔλʹର͢Δཁٻ(Action)Λ͠·͢
▸ Reactɺ͜ͷΈͷதͰViewʹΘΕΔ͜ͱΛਪ͍ͯ͠·͢
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ BackboneʹFluxͷ֓೦ΛऔΓೖΕΔʹ ▸ ͷൣғΛ୲͍ͬͯΔCollectionModelΛׂ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part.5 ·ͱΊ ▸ ݱঢ়ViewModelʹϩδοΫ͕ࢄΒ͔͍ͬͯΔ͕ɺ ActionΛऔΓೖΕͨ͜ͱͰɺߋ৽ͱऔಘΛ͢Δ͜ͱ͕Ͱ͖ɺ ϩδοΫͷཧͱංେԽΛ͑ΒΕͦ͏Ͱͨ͠ ▸ ͔͠͠ɺDispatcherͱ͔ɺViewͱModelΛDispatcherͰඥ͚Δ ෦ͱ͔ɺಠ࣮ࣗ͢Δͱ͜Ζ͕৭ʑ͋ͬͯɺ݁ہBackbone
Ϣʔβʹͱֶͬͯशίετ͕͔͔ͬͯ͠·͏ײ͡Ͱ͢ ▸ ͰɺFLUXɺCQRS + Event Sourcingύλʔϯͱ͍ͬͨҰํ ͷσʔλϑϩʔτϨϯυͳͷͰੋඇ͓͓͖͍͑ͯͨ͞Ͱ͢Ͷɻ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ࣮͜ͷࠒʹ ▸ ͳΜ͔ٕज़తෛ࠴ଟա͗ͯɺReactʹஔ͖͑ʹ͍͘ॴ͕ ͋Γ͗͢Δͱ͍͏ݱ࣮ʹ໘͍ͯ͠·ͨ͠ɻ ▸ ݁ہϓϩδΣΫτෛ࠴ฦࡁͱ৽ن։ൃʹ͠·ͨ͠ɻ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ ReactԽ Part.6 : BackboneΊΔ ▸ ৽ن։ൃϓϩδΣΫτ͕࢝·ΓɺτϨϯυͷReduxͱɺ Facebook͕ϝϯςφϯε͢ΔFlux UtilsͰൺֱ͢Δ͜ͱʹͳΓ ·ͨ͠ɻ
▸ ͜ͷ2ͭͷେ͖ͳҧ͍ɺReduxʹ1ͭͷΦϒδΣΫτʹΞϓ ϦέʔγϣϯશମͷεςʔτΛ·ͱΊΔݪଇ͕͋Δɺͱ͍͏ͱ ͜ΖͰ͢ɻ ▸ ElmͷӨڹΛड͚ͨReduxɺؔܕϓϩάϥϛϯάͷ׆༻ʹ Αͬͯอकੑͷߴ͍ίʔυΛॻ͚ΔͷͰ͍͍ͱࢥ͍·ͨ͠ɻ
طଘϓϩμΫτͷViewΛReactʹஔ͖͑Δ Part.6 ·ͱΊ ▸ ͔ͳΓࡉ͔͍ίʔσΟϯάνΣοΫઃఆͰ͋Δeslint-config- airbnbΛซ༻͢Δͱ͍͍ͱࢥ͍·͢ɻ ▸ FacebookJS੩తܕνΣοΧʔͷFlowซͤͯಋೖ͠ɺ JSʹڧ͍ܕ͚ͱnullඇڐ༰Λ͚ͭΔͱΑΓ҆৺Ͱ͠ΐ͏ɻ
THAT'S IT. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠