動手實作一個 Isomorphic flux
一種溝通工具,讓 view 跟 store 約定好要說什麼
避免雞同鴨講
Fluxxx.action({
go: function() {
var flux = this.flux;
flux.getActions().go.dispatch({abc: 123});
}
});
//view
this.flux().getActions().go()
統一資料來源
Single Source of Truth
Fluxxx.store('list', function() {
var flux = this.flux;
var actions = flux.getActions();
var list = [1, 2, 3];
return {
getList: function() {
return list;
},
onPop: function() {
list.pop();
this.emit('change');
},
dehydrate: function() {
return [list];
},
rehydrate: function(state) {
list = state[0];
},
dispatchToken: flux.listenTo('list', function(on) {
on(actions.pop, 'onPop');
}
}
});
div
input
span
listeners
click、keydown、mosuedown、hover ...
div
input
span
listeners
click、keydown、mosuedown、hover ...
dispatcher
How to render after all stores are populated?
How to render after all stores are populated?
var actions = Fluxx.action({
all: function() {
var flux = this.flux;
if(flux.getStore('list').hasInitialized())
return;
return fetch('/api/list.json').then(function(res) {
return res.json();
}).then(function(data) {
flux.getActions().initial(data);
return data;
});
}})
How to render after all stores are populated?
action
dispache
How to render after all stores are populated?
action
dispache
ajax
收集 promise
要 return action 的 promise
var actions = Fluxx.action({
all: function() {
var flux = this.flux;
return fetch('/api/list.json').then(function(res) {
return res.json();
});
}})
app.get('/', function() {
...
flux.ready(function() {
var html = React.renderToString(app);
res.render('index', {html: html});
});
...
});
Singleton Issue
Server 端禁止共用 dispatcher
var Dispatcher = require('flux').Dispatcher;
module.exports = new Dispatcher();
//action
var dispatcher = require('dispatcher');
var action = {
all: function() {
dispatcher.dispatch({type: 'all'});
}
};
//store
var dispatcher = require('dispatcher');
var store = assign({}, EventEmitter.prototype, {
onAll: function() {
}
});
dispatcher.register(function(payload) {
if(payload.type == 'all') {
store.onAll(payload)
}
})
//action
Fluxx.action({
all: function() {
var flux = this.flux;
}
});
//store
Fluxx.store('list', function() {
var flux = this.flux;
})
app.get('/', function() {
var flux = new Fluxxx();
});
Fluxxx.store('list', function() {
var flux = this.flux;
var actions = flux.getActions();
var list = [1, 2, 3];
return {
dehydrate: function() {
return [list];
},
rehydrate: function(state) {
list = state[0];
}
}
});
var data = <?=json_encode($data);?>
後端的資料吐到前端塞回 store 裡面
//server
app.get('/', function() {
var flux = new Fluxxx();
React.renderToString(app);
flux.ready(function() {
var html = React.renderToString(app);
res.render('index', {html: html, dehydratedStr: JSON.stringify(flux.dehydrate())});
});
});
//browser
<script>var __dehydrated = <%- dehydratedStr %></script>
var flux = new Fluxx();
flux.rehydrate(window.__dehydrated);
React.render(<App flux={flux} />, document.getElementById('container'));