11_Workoutlogger ---ReactJS and Flux: Learn By Building 10 Projects
来源:互联网 发布:马小丝的淘宝店 编辑:程序博客网 时间:2024/06/05 09:09
学习编程的最好方法就是去编程。
这篇笔记项目来自于:
https://www.udemy.com/reactjs-and-flux-learn-by-building-10-projects/ 的第11课。
最终效果如图:
这个项目是单页面应用,使用的是客户端的渲染,没有用到服务器。
package.json
{ "name": "workoutlogger", "version": "1.0.0", "description": "Workout Logger", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Morphues Cao", "license": "ISC", "devDependencies":{ "browserify":"*", "gulp":"*", "reactify":"*", "vinyl-source-stream":"*", "object-assign":"*" }, "dependencies":{ "react":"^0.14.7", "react-dom":"^0.14.7", "flux":"^2.1.1" }}
使用gulp进行编译,复制和监控。gulpfile.js
//path %PATH%;.\node_modules\.binvar gulp = require('gulp');var browserify = require('browserify');var reactify = require('reactify');var source = require('vinyl-source-stream');gulp.task('browserify',function(){ browserify('./src/js/main.js') .transform('reactify') //jsx -> js .bundle() .pipe(source('main.js')) .pipe(gulp.dest('dist/js'));});gulp.task('copy',function(){ gulp.src('src/index.html') .pipe(gulp.dest('dist')); gulp.src('src/css/*.*') .pipe(gulp.dest('dist/css')); gulp.src('src/js/vendors/*.*') .pipe(gulp.dest('dist/js'));});gulp.task('default',['browserify','copy'],function(){ return gulp.watch('src/**/*.*',['browserify','copy']);});
目录结构:
参考flux的unidirectional data flow.:
对应的文件结构就更容易理解:
index.html
<html> <head> <title>Workout logger</title> <link rel="stylesheet" href="css/bootstrap.css"/> <link rel="stylesheet" href="css/style.css"/> </head> <body> <div class="row"> <div class="col-md-4 col-md-offset-4"> <div id="app">TEST APP</div> </div> </div> <script src="js/jquery.js"></script> <script src="js/main.js"></script> </body></html>
js/main.js
var App = require('./components/App');var React = require('react');var ReactDOM = require('react-dom');var AppAPI = require('./utils/AppAPI.js')var StartData = require('./startData.js');if(localStorage.getItem('workouts') == null){ StartData.init();}AppAPI.getWorkouts();ReactDOM.render( <App />, document.getElementById('app'));
js/components/App.js
var React = require('react');var AppActions = require('../actions/AppActions');var AppStore = require('../stores/AppStore');var AddForm = require('./AddForm.js');var Workouts = require('./Workouts.js');function getAppState(){ return { showForm: AppStore.getShowForm(), workouts: AppStore.getWorkouts() }}var App = React.createClass({ getInitialState: function(){ return getAppState(); }, componentDidMount:function(){ AppStore.addChangeListener(this._onChange); }, componentWillUnmount:function(){ AppStore.removeChangeListener(this._onChange) }, onShowFormClick:function(e){ e.preventDefault(); AppActions.showForm(); }, render: function(){ console.log(this.state.workouts) if(this.state.showForm){ var form = <AddForm /> }else{ var form = ''; } return ( <div> <h1 className="text-center page-header">WorkoutLogger</h1> <a onClick={this.onShowFormClick} href="#" className="btn btn-primary btn-block">Add Workout</a> <br/> {form} <br/> <Workouts workouts = {this.state.workouts} /> <br/> </div> ) }, _onChange: function(){ this.setState(getAppState()); }});module.exports = App;
js/components/AddForm.js
var React = require('react');var AppActions = require('../actions/AppActions');var AppStore = require('../stores/AppStore');var AddForm = React.createClass({ render: function(){ return ( <form onSubmit={this.onSubmit}> <div className="form-group"> <select className="form-control" ref="type"> <option value="Jogging">Jogging</option> <option value="Weight Lifting">Weight Lifting</option> <option value="Elliptical">Elliptical</option> <option value="Yoga">Yoga</option> <option value="Other">Other</option> </select> </div> <div className="form-group"> <input type="text" className="form-control" ref="minutes" placeholder="Minutes"/> </div> <div className="form-group"> <input type="text" className="form-control" ref="miles" placeholder="Miles(Optional)"/> </div> <button type="submit" className="btn btn-default btn-block">Log Workout</button> </form> ) }, onSubmit: function(e){ e.preventDefault(); var workout = { id: this.generateId(), type:this.refs.type.value.trim(), minutes:this.refs.minutes.value.trim(), miles:this.refs.miles.value.trim(), date:new Date() } //console.log(workout); AppActions.addWorkout(workout); }, generateId: function(){ var id=''; var possible = '0123456789'; for(var i=0;i<5;i++){ id += possible.charAt(Math.floor(Math.random() * possible.length)); } return id; }});module.exports = AddForm;
js/components/Workouts.js
var React = require('react');var AppActions = require('../actions/AppActions');var AppStore = require('../stores/AppStore');var Workout = require('./Workout');var Workouts = React.createClass({ render: function(){ return ( <ul className="list-group"> { this.props.workouts.map(function(workout,i){ // console.log(workout); return( <Workout workout={workout} key={i} /> ) }) } </ul> ) }});module.exports = Workouts;
js/components/Workout.js
var React = require('react');var AppActions = require('../actions/AppActions');var AppStore = require('../stores/AppStore');var Workout = React.createClass({ render: function(){ if(this.props.workout.miles != ''){ var miles = ' | '+this.props.workout.miles + 'Miles'; }else{ var miles = ''; } return ( <li className="list-group-item"> {this.props.workout.type} - {this.props.workout.minutes} Minutes {miles} <a href="#" onClick={this.onDelete.bind(this,this.props.workout.id)} className="delete">X</a> </li> ) }, onDelete:function(i,j){ AppActions.removeWorkout(i); }});module.exports = Workout;
js/actions/AppActions.js
var AppDispatcher = require('../dispatcher/AppDispatcher');var AppConstants = require('../constants/AppConstants');var AppActions = { showForm: function(){ // console.log('AppAction: Searching for movie' + movie.title); AppDispatcher.handleViewAction({ actionType: AppConstants.SHOW_FORM }); }, addWorkout:function(workout){ AppDispatcher.handleViewAction({ actionType: AppConstants.ADD_WORKOUT, workout:workout }); }, receiveWorkouts:function(workouts){ AppDispatcher.handleViewAction({ actionType: AppConstants.RECEIVE_WORKOUTS, workouts:workouts }); }, removeWorkout:function(workoutId){ AppDispatcher.handleViewAction({ actionType: AppConstants.REMOVE_WORKOUT, workoutId:workoutId }); }}module.exports = AppActions;
js/dispatcher/AppDispatcher.js
var Dispatcher = require('flux').Dispatcher;var assign = require('object-assign');var AppDispatcher = assign(new Dispatcher(),{ handleViewAction: function(action){ var payload = { source:"VIEW_ACTION", action: action } this.dispatch(payload); }});module.exports = AppDispatcher;
js/stores/AppStore.js
var AppDispatcher = require('../dispatcher/AppDispatcher');var AppConstants = require('../constants/AppConstants');var EventEmitter = require('events').EventEmitter;var assign = require('object-assign');var AppAPI = require('../utils/AppAPI.js')var CHANGE_EVENT = 'change';var _workouts = [];var _showForm = false;var AppStore = assign({},EventEmitter.prototype,{ showForm: function(){ _showForm = true; }, getShowForm: function(){ return _showForm; }, addWorkout:function(workout){ _workouts.push(workout); }, getWorkouts:function(){ return _workouts; }, receiveWorkouts:function(workouts){ _workouts = workouts; }, removeWorkout:function(workoutId){ // var index =_workouts.findIndex(x => x.id === workoutId); function findIndex(_workouts,workoutId){ for(var i=0,len=_workouts.length;i<len;i++){ if(_workouts[i]._id === workoutId){ return i; } } return -1; } var index = findIndex(_workouts,workoutId); _workouts.splice(index,1); }, emitChange:function(){ this.emit(CHANGE_EVENT); }, addChangeListener: function(callback){ this.on('change',callback); }, removeChangeListener:function(callback){ this.removeListener('change',callback); }});AppDispatcher.register(function(payload){ var action = payload.action; switch(action.actionType){ case AppConstants.SHOW_FORM: AppStore.showForm(); AppStore.emit(CHANGE_EVENT); break; case AppConstants.ADD_WORKOUT: AppStore.addWorkout(action.workout); AppAPI.addWorkout(action.workout); AppStore.emit(CHANGE_EVENT); break; case AppConstants.RECEIVE_WORKOUTS: AppStore.receiveWorkouts(action.workouts); AppStore.emit(CHANGE_EVENT); break; case AppConstants.REMOVE_WORKOUT: AppStore.removeWorkout(action.workoutId); AppAPI.removeWorkout(action.workoutId); AppStore.emit(CHANGE_EVENT); break; } return true;})module.exports = AppStore;
js/utils/AppAPI.js
var AppActions = require('../actions/AppActions');module.exports = { addWorkout: function(workout){ console.log('Saving Workout...'); var workouts = JSON.parse(localStorage.getItem('workouts')); workouts.push(workout); console.log('addWorkout:',workouts); localStorage.setItem('workouts',JSON.stringify(workouts)); }, getWorkouts:function(){ var workouts = JSON.parse(localStorage.getItem('workouts')); AppActions.receiveWorkouts(workouts); }, removeWorkout:function(workoutId){ var workouts = JSON.parse(localStorage.getItem('workouts')); for(var i=0;i<workouts.length;i++){ if(workouts[i].id ==workoutId){ workouts.splice(i,1); } } localStorage.setItem('workouts',JSON.stringify(workouts)); }}
js/startData.js
module.exports ={ init:function(){ localStorage.clear(); localStorage.setItem('workouts',JSON.stringify([ { id:0001, type:'Jogging', minutes:20, miles:2, date: new Date() }, { id:0002, type:'Yoga', minute:40, miles:'', date:new Date() } ])); }}
阅读全文
1 0
- 11_Workoutlogger ---ReactJS and Flux: Learn By Building 10 Projects
- reactjs设计架构---Flux 从愣逼到哇哦
- ASP.NET at Work: Building 10 Enterprise Projects
- ReactJS学习系列课程附加(Flux应用架构)
- Adblock Plus and all related projects are governed by a module ownership system.
- flux
- flux
- flux
- Flux
- HTML5 and JavaScript Projects
- HTML5 and JavaScript Projects
- Building issues of open source projects
- 【spring】Building Java Projects with Maven
- 【Spring】Building Java Projects with Gradle
- CMUSphinx Learn - Building Language Model
- Projects owned by limodev.cn
- Learn By Doing & 随笔
- Learn Hibernate by Examples
- SpringBoot整合shiro框架
- Standard 1.1.x VM与Standard VM的区别
- mysql xtrabackup备份恢复单表
- Java设计模式之策略模式
- 读java编程建议--笔记三
- 11_Workoutlogger ---ReactJS and Flux: Learn By Building 10 Projects
- 练习5
- eclipse报错"错误: 找不到或无法加载主类 jdk1.7"解决方案
- c语言中的指针
- Redis快速入门
- java只安装了jre,没有安装jdk,是不能运行源代码
- Ubuntu 16.04 桌面壁纸问题解决
- Eclipse提示:No JREs in workspace compatible with specified execution environment
- 2-3查找树总结