Facebook: React-Flux
近日前端火紅的議題
社群戰火持續燃燒中
Michael Hsu.tw Nov, 2014
NTUIM R02 BAEIR LAB 徐承志
沒錯,就只是導讀
因為也根本還沒在專案實作過
目前 v0.12 還不停更新
暫時不花太多心力在語法上
讓我們感受一下
React-Flux Design Pattern
What's React
A JavaScript library for creating user interfaces.
Renders your UI and responds to events.
AKA: The V in MVC.
React Design
-
Separation of concerns
-
Re-render
-
VDOM
Separation of concerns
大家都愛的關注點分離
Server-Side MVC
Rails, Express, Sails ...
Client-Side MVC
Angular.js ...
Model - View - Controller 三部分的邏輯要拆開,中間鬆散的綁在一起。
前端 MVC 思維流程大概是這樣
讓我們從另一個角度
Use components to separate your concerns.
Yahoo Mail Case
在 React 的世界中
Build components, not templates.
React Componets
用比較專業的說法:
A highly cohesive building block for UIs loosely coupled with other components.
高內聚 n. high cohesion
低耦合 n. low coupling
Components 優點
-
Reusable
-
Composable: 元件可層層組合
-
Unit testable
Re-render the whole app on every update
採取「一律重繪」的原則
在我大一時候的認知
所有網頁都是透過 Refresh (F5) 來更新頁面
Angular Data Binding
頁面上觸發 Event,有關 angular 的 data binding 進入消化循環 (watch list, dirty checking),進而操作 DOM ,re-Render 頁面。
大型專案非常多的話勒?
Web Worker?
Why React 效能好
VDOM!
Virtual DOM
讓 Re-Rendering 頁面變得廉價
VDOM
- It’s a pure Javascript, in-memory representation of the DOM
- 底層 API 的功勞:不直接與 DOM 接觸。
- 當頁面需要更動,先產生一個假的 Virtual DOM subtree
- 跟原本的DOM 做 Diff (樹的比較很多博士在研究)
- 在記憶體內進⾏⾼效能運算與批次更新
- 因為有效減少對 DOM 的操作以及批次更新,因⽽加快反應速度 => 60 FPS 不是夢想
React Design
-
Separation of concerns
-
Re-render
-
VDOM
React Data-Flow
One-Way data flow
單向資料流
Traditional Data Flows Type
- No framework: Any component can communicate with any other component
- Angular: 2-way data binding and $digest loop
- Backbone: Pub-sub
- React: 1-way data flow (類似 Pub-sub)
Angular 碰到的問題
點擊網頁觸發資料 Model 改變,進而影響其他的頁面的元素,頁面被動的更新難免會碰到漏掉的情況,尤其是在複雜的大型專案上。
React 思維
- React 認為 UI 就是一個簡單的 State Machine。
- 從 UI 的角度思考,UI 本身俱有多種 State,並且負責把這些狀態輸出呈現。
- 這樣做可以輕易讓你的 UI 保持一致。
- 只要單純更新 Component 的 State,接著根據狀態 Render 輸出新的 UI。
- React 透過較有效率的方式協助你更新 DOM 。
React 思維
由狀態去驅動改變 Components
操作 State
this.state vs this.props
只有變動的資料才需要放到 state
setState(data, callback)
Example 1: Simple Component
<!DOCTYPE html>
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
// ... 待會的關注點
</script>
</body>
</html>
Include React.js (0.12.0 版)
在瀏覽器將 JSX 編譯成 JS
進入點,剩下 dom 都在 react 裏生成
JSX: 在 JS 裡面寫 HTML
Example 1: Simple Component
var HelloWorld = React.createClass({
render: function() {
return (
<p>
Hello, <input type="text" placeholder="Your name here" />!
It is {this.props.date.toTimeString()}
</p>
);
}
});
setInterval(function() {
React.render(
<HelloWorld date={new Date()} />,
document.getElementById('example')
);
}, 500);
Create a component
props: Properties
Render a ReactElement into the DOM
Example 2: Multi Components
<!DOCTYPE html>
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
// ... 待會的關注點
</script>
</body>
</html>
似曾相識?沒錯,只有進入點
Example 2: Multi Components
var Avatar = React.createClass({
render: function() {
return (
<div>
<ProfilePic username={this.props.username} />
<ProfileLink username={this.props.username} />
</div>
);
}
});
React.render(
<Avatar username="pwh" />,
document.getElementById('example')
);
Avatar owns the
div, ProfilePic and ProfileLink instances
var ProfilePic = React.createClass({
render: function() {
return (
<img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
);
}
});
var ProfileLink = React.createClass({
render: function() {
return (
<a href={'http://www.facebook.com/' + this.props.username}>
{this.props.username}
</a>
);
}
});
an owner is the component that sets the props of other components
Example 3: State
<!DOCTYPE html>
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
// ... 待會的關注點
</script>
</body>
</html>
似曾相識?沒錯,只有進入點
Example 3: State
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'unlike';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
React.renderComponent(
<LikeButton />,
document.getElementById('example')
);
setState(data, callback) ,這個方法會把資料 data 整合進 this.state 接著重新渲染元件。
Component Lifecycle
Component Lifecycle
What's Flux
Application architecture for building client-side web applications
Flux
-
Unidirectional data flow architecture
-
just an architecture, not a framework.
-
not MVC,可以看成 MC 的功能
No two-way binding
因為 two-way binding 會造成串聯式的觸發更新(cascading updates),會讓結果難以預期。
Flux 的概念很簡單
1. Views 驅動 update(data) 事件
2. Action 將 data 送到 Dispatcher
3. Dispatcher 播送 payload 給所有 Stores
4. NodeJS’s EventEmitter 播送給 Views
5. View 跟 Store 拿 State
1
2
3
4
payload
5
主要元素
-
Dispatcher: 調度中心
-
Stores: state & logic
-
Views: React components
-
Actions: helper methods
太過抽象
直接開始 Trace Code
前情提要
- Browserify: Bundling Node Modules for the Browser
- Gulp: The Streaming Build System
- LiveScript: a language which compiles to JavaScript.
Quick Starter Project
Flux 的概念很簡單
1. Views 驅動 update(data) 事件
2. Action 將 data 送到 Dispatcher
3. Dispatcher 播送 payload 給所有 Stores
4. NodeJS’s EventEmitter 播送給 Views
5. View 跟 Store 拿 State
1
2
3
4
payload
5