actions
counter
const increment1 = ()=> {
return {
type: 'INCREMENT_COUNTER',}
};
const decrement1 = ()=> {
return {type: 'DECREMENT_COUNTER'}
};
module.exports = {
increment1,decrement1
};
infoMember
const setInfoMember = (payload) => {
return {
type: 'SET_MEMBER_INFO',payload
}
}
const changeInfo = (payload) => {
return {
type: 'CHANGE_INFO',payload
}
}
module.exports = {
setInfoMember,changeInfo
}
reducers
counter
export default function counter(state = 0,action) {
switch (action.type) {
case 'INCREMENT_COUNTER':
return state + 1;
case 'DECREMENT_COUNTER':
return state - 1;
default:
return state
}
};
infoMember
export default function infoMember(state = {},action) {
let _state = Object.assign({},state);
switch (action.type) {
case 'SET_MEMBER_INFO':
return action.payload;
case 'CHANGE_INFO':
_state.script = action.payload;
return _state;
default:
return state;
}
}
index.js
import { combineReducers } from 'redux'
import counter from './counter'
import infoMember from './infoMember'
//使用redux的combineReducers方法将所有reducer打包起来
const rootReducer = combineReducers({
counter,infoMember
});
export default rootReducer;
App.js
import { connect } from 'react-redux'
import actions from '../actions/counter';
import actions2 from '../actions/infoMember';
import React,{Component} from 'react'
class Counter extends Component {
constructor(props) {
super(props);
this.add = this.add.bind(this);
this.reduce = this.reduce.bind(this);
this.changeInfo = this.changeInfo.bind(this);
}
componentDidMount() {
console.log(this.props.infoMember); // {}
}
add() {
this.props.dispatch(actions.increment1());
this.props.dispatch(actions2.setInfoMember({id: '9932939293',script: 'Try my best'}));
}
reduce() {
this.props.dispatch(actions.decrement1());
}
changeInfo() {
this.props.dispatch(actions2.changeInfo('Come on'));
}
render() {
return (
<div>
<p>
Clicked: {this.props.counter} times
{' '}
<button onClick={this.add}>+</button>
{' '}
<button onClick={this.reduce}>-</button>
{' '}
</p>
<p onClick={this.changeInfo}>this.props.infoMember: {this.props.infoMember.id} - {this.props.infoMember.script}</p>
</div>
)
}
}
// //将state.counter绑定到props的counter
// const mapStateToProps = (state) => {
// return {
// counter: state.counter
// }
// };
// //将action的所有方法绑定到props上
// const mapDispatchToProps = (dispatch,ownProps) => {
// return {
// add: (...args) => dispatch(actions.increment1(...args)),
// reduce: (...args) => dispatch(actions.decrement1(...args))
// }
// };
//通过react-redux提供的connect方法将我们需要的state中的数据和actions中的方法绑定到props上
export default connect(state => (state))(Counter)
入口文件
import React from 'react';
import ReactDom from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import reducer from './reducers/index.js';
import App from './containers/App.js';
let store = createStore(reducer);
ReactDom.render(
<Provider store={store}>
<App/>
</Provider>,document.getElementById('root')
);
index.html
<!DOCTYPE html>
<html lang="en">
<head>Counter</head>
<body>
<div id="root">
</div>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>
app.js
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static(__dirname + '/public'));
app.use('/',function (req,res) {
res.sendFile(path.resolve('./public/index.html'));
});
app.listen(3000,function () {
console.log('server started at http://localhost:3000'); // eslint-disable-line no-console
});
module.exports = app;
webpack配置 webpack.config.js
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devtool: 'eval-source-map',//由bundle.js映射到origin文件,容易在浏览器调试
entry: __dirname + "/public/src/main.js",output: {
path: __dirname + '/public',filename: "bundle.js"
},module: {
/*test: A regular expression that matches the file extensions that should run through this loader (required).
loader: The name of the loader (required).
include / exclude: Optional setting to manually set which folders and files the loader should explicitly add or ignore.
query: The query setting can be used to pass Additional options to the loader.
*/
loaders: [
{
test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)
exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选)
loader: 'babel-loader',query: {
presets: ['es2015','react']
}
},{test: /\.css$/,loader: "style-loader!css-loader"},{test: /\.png$/,loader: "file-loader"},{test: /\.jpg$/,loader: "file-loader"}
]
}
};