此书讲得蛮详细,
从Flux一步一步过渡到Redux。
写过的代码舍不得扔,
立此存照吧。
我有几张阿里云幸运券分享给你,用券购买或者升级阿里云相应产品会有特惠惊喜哦!把想要买的产品的幸运券都领走吧!快下手,马上就要抢光了。
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import ControlPanel from './views/ControlPanel'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(<ControlPanel />,document.getElementById('root')); registerServiceWorker();
AppDispatcher.js
import {Dispatcher} from 'flux'; export default new Dispatcher();
ActionTypes.js
export const INCREMENT = 'increment'; export const DECREMENT = 'decrement';
Actions.js
import * as ActionTypes from './ActionTypes'; import AppDispatcher from './AppDispatcher'; export const increment = (counterCaption) => { AppDispatcher.dispatch({ type: ActionTypes.INCREMENT,counterCaption: counterCaption }); }; export const decrement = (counterCaption) => { AppDispatcher.dispatch({ type: ActionTypes.DECREMENT,counterCaption: counterCaption }); };
CounterStore.js
import AppDispatcher from '../AppDispatcher'; import * as ActionTypes from '../ActionTypes'; import {EventEmitter} from 'events'; const CHANGE_EVENT = 'changed'; const counterValues = { 'First': 0,'Second': 10,'Third': 30 }; const CounterStore = Object.assign({},EventEmitter.prototype,{ getCounterValues: function() { return counterValues; },emitChange: function() { this.emit(CHANGE_EVENT); },addChangeListener:function(callback) { this.on(CHANGE_EVENT,callback); },removeChangeListener: function(callback) { this.removeListener(CHANGE_EVENT,callback); } }); CounterStore.dispatchToken = AppDispatcher.register((action)=> { if (action.type === ActionTypes.INCREMENT) { counterValues[action.counterCaption]++; CounterStore.emitChange(); } else if (action.type === ActionTypes.DECREMENT) { counterValues[action.counterCaption]--; CounterStore.emitChange(); } }); export default CounterStore;
SummaryStore.js
import AppDispatcher from '../AppDispatcher'; import * as ActionTypes from '../ActionTypes'; import CounterStore from './CounterStore'; import {EventEmitter} from 'events'; const CHANGE_EVENT = 'changed'; function computerSummary(counterValues) { let summary = 0; for (const key in counterValues) { if (counterValues.hasOwnProperty(key)) { summary += counterValues[key]; } } return summary; } const SummaryStore = Object.assign({},{ getSummary: function() { return computerSummary(CounterStore.getCounterValues()); },addChangeListener: function(callback) { this.on(CHANGE_EVENT,callback); } }); SummaryStore.dispatchToken = AppDispatcher.register((action) => { if ((action.type === ActionTypes.INCREMENT) || (action.type === ActionTypes.DECREMENT)) { AppDispatcher.waitFor([CounterStore.dispatchToken]); SummaryStore.emitChange(); } }); export default SummaryStore;
CounterPanel.js
import React,{ Component } from 'react'; import Counter from './Counter'; import Summary from './Summary'; const style = { margin: '20px' }; class ControlPanel extends Component { render() { return ( <div style={style}> <Counter caption="First" /> <Counter caption="Second" /> <Counter caption="Third" /> <hr /> <Summary /> </div> ); } } export default ControlPanel;
Counter.js
import React,{ Component } from 'react'; import PropTypes from 'prop-types'; import * as Actions from '../Actions.js'; import CounterStore from '../stores/CounterStore.js'; const buttonStyle = { margin: '10px' }; const propTypes = { caption: PropTypes.string.isrequired }; class Counter extends Component { constructor(props) { super(props); this.onClickIncrementButton = this.onClickIncrementButton.bind(this); this.onClickDecrementButton = this.onClickDecrementButton.bind(this); this.onChange = this.onChange.bind(this); this.state = { count: CounterStore.getCounterValues()[props.caption] } } shouldComponentUpdate(nextProps,nextState) { return (nextProps.caption !== this.props.caption) || (nextState !== this.state.count); } componentDidMount() { CounterStore.addChangeListener(this.onChange); } componentWillUnmout() { CounterStore.removeChangeListener(this.onChange); } onChange() { const newCount = CounterStore.getCounterValues()[this.props.caption]; this.setState({count: newCount}); } onClickIncrementButton() { Actions.increment(this.props.caption); } onClickDecrementButton() { Actions.decrement(this.props.caption); } render() { const {caption} = this.props; return ( <div> <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button> <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button> <span> { caption } count: {this.state.count}</span> </div> ); } } Counter.defaultProps = { initValue: 0,onUpdate: f => f }; Counter.propTypes = propTypes export default Counter;
Summary.js
import React,{Component} from 'react'; import SummaryStore from '../stores/SummaryStore'; class Summary extends Component { constructor(props) { super(props); this.onUpdate = this.onUpdate.bind(this); this.state = { sum: SummaryStore.getSummary() } } componentDidMount() { SummaryStore.addChangeListener(this.onUpdate); } componentWillUnmount() { SummaryStore.removeChangeListener(this.onUpdate); } onUpdate() { this.setState({ sum: SummaryStore.getSummary() }) } render() { return ( <div>Total Count: {this.state.sum}</div> ); } } export default Summary;
阅读原文