├── .gitignore
├── .babelrc
├── assets
└── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.ttf
│ ├── glyphicons-halflings-regular.woff
│ ├── glyphicons-halflings-regular.woff2
│ └── glyphicons-halflings-regular.svg
├── src
├── containers
│ ├── index.js
│ ├── DevTools.js
│ ├── Antd.js
│ ├── Foo.js
│ ├── Home.js
│ ├── Bar.js
│ └── App.js
├── constants.js
├── reducers
│ ├── index.js
│ └── count.js
├── components
│ └── List.js
├── routes.js
├── store
│ └── configureStore.js
└── actions
│ └── count.js
├── dist
├── node_modules
│ └── font-awesome
│ │ └── fonts
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
└── assets
│ └── fonts
│ └── glyphicons-halflings-regular.svg
├── README.md
├── index.html
├── index.js
├── webpack.config.js
├── data.json
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /mobile/node_modules
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react", "stage-1"],
3 | "plugins": [["antd", { "style": "css" }], "transform-object-assign"]
4 | }
5 |
--------------------------------------------------------------------------------
/assets/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/assets/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/assets/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/assets/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/assets/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/assets/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/assets/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/assets/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/src/containers/index.js:
--------------------------------------------------------------------------------
1 | export App from './App'
2 | export Home from './Home'
3 | export Foo from './Foo'
4 | export Bar from './Bar'
5 | export Antd from './Antd'
--------------------------------------------------------------------------------
/dist/node_modules/font-awesome/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/dist/node_modules/font-awesome/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/dist/node_modules/font-awesome/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/dist/node_modules/font-awesome/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/dist/node_modules/font-awesome/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/dist/node_modules/font-awesome/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/dist/node_modules/font-awesome/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luozhihao/react-redux-demo/HEAD/dist/node_modules/font-awesome/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/src/constants.js:
--------------------------------------------------------------------------------
1 | // action常量
2 | export const INCREASE = 'INCREASE'
3 | export const DECREASE = 'DECREASE'
4 | export const LOADDATA = 'LOADDATA'
5 | export const GETSUCCESS = 'GETSUCCESS'
6 | export const REFRESHDATA = 'REFRESHDATA'
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## react-redux-demo
2 | react+redux+react-router实例
3 |
4 | ## 文档说明
5 | 地址:[http://www.cnblogs.com/luozhihao/p/5660496.html](http://www.cnblogs.com/luozhihao/p/5660496.html)
6 |
7 | ## 本地运行
8 | > npm install
9 |
10 | > npm run start
11 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | react-router-redux basic example
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | // reducers/index.js
2 | import { combineReducers } from 'redux' // 利用combineReducers 合并reducers
3 | import { routerReducer } from 'react-router-redux' // 将routerReducer一起合并管理
4 | import update from './count' // 引入update这个reducer
5 |
6 | export default combineReducers({
7 | update,
8 | routing: routerReducer
9 | })
--------------------------------------------------------------------------------
/src/components/List.js:
--------------------------------------------------------------------------------
1 | // 动态数据列表
2 | import React, { Component, PropTypes } from 'react'
3 |
4 | export default class List extends Component {
5 | render() {
6 | return(
7 | {this.props.text}
8 | )
9 | }
10 | }
11 |
12 | List.propTypes = {
13 | text: PropTypes.string.isRequired
14 | }
--------------------------------------------------------------------------------
/src/containers/DevTools.js:
--------------------------------------------------------------------------------
1 | // 调试工具
2 | import React from 'react'
3 | import { createDevTools } from 'redux-devtools'
4 | import LogMonitor from 'redux-devtools-log-monitor'
5 | import DockMonitor from 'redux-devtools-dock-monitor'
6 |
7 | const DevTools = createDevTools(
8 |
9 |
10 |
11 | )
12 |
13 | export default DevTools
--------------------------------------------------------------------------------
/src/routes.js:
--------------------------------------------------------------------------------
1 | import React from 'react' // 引入react
2 | import { Route, IndexRoute } from 'react-router' // 引入react路由
3 | import { App, Home, Foo, Bar, Antd } from './containers' // 引入各容器组件
4 |
5 | export default (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | )
--------------------------------------------------------------------------------
/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import thunk from 'redux-thunk' // redux-thunk 支持 dispatch function,并且可以异步调用它
2 | import createLogger from 'redux-logger' // 利用redux-logger打印日志
3 | import { createStore, applyMiddleware, compose } from 'redux' // 引入redux createStore、中间件及compose
4 | import DevTools from '../containers/DevTools' // 引入DevTools调试组件
5 |
6 | // 调用日志打印方法
7 | const loggerMiddleware = createLogger()
8 |
9 | // 创建一个中间件集合
10 | const middleware = [thunk, loggerMiddleware]
11 |
12 | // 利用compose增强store,这个 store 与 applyMiddleware 和 redux-devtools 一起使用
13 | const finalCreateStore = compose(
14 | applyMiddleware(...middleware),
15 | DevTools.instrument(),
16 | )(createStore)
17 |
18 | export default finalCreateStore
--------------------------------------------------------------------------------
/src/containers/Antd.js:
--------------------------------------------------------------------------------
1 | // 结合antd
2 | import React, { Component } from 'react'
3 | import { connect } from 'react-redux'
4 |
5 | // 引入Antd组件及样式
6 | import { Collapse } from 'antd'
7 | import 'font-awesome/css/font-awesome.min.css'
8 | const Panel = Collapse.Panel
9 |
10 | const text = `
11 | A dog is a type of domesticated animal.
12 | Known for its loyalty and faithfulness,
13 | it can be found as a welcome guest in many households across the world.
14 | `;
15 |
16 | class Antd extends Component {
17 | render() {
18 | return (
19 |
20 |
21 | {text}
22 |
23 |
24 | {text}
25 |
26 |
27 | {text}
28 |
29 |
30 | )
31 | }
32 | }
33 |
34 | export default connect()(Antd)
--------------------------------------------------------------------------------
/src/containers/Foo.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react' // 引入React
2 | import { connect } from 'react-redux' // 引入connect
3 | import List from '../components/List' // 引入展示组件List
4 |
5 | class Foo extends Component {
6 | render() {
7 |
8 | // 通过this.props获取到lists的值
9 | const { lists } = this.props
10 |
11 | return(
12 |
13 |
14 | {/*将值传入展示组件*/}
15 | { lists.map((e, index) =>
16 |
17 | )}
18 |
19 |
20 | )
21 | }
22 | }
23 |
24 | // 验证组件中的参数类型
25 | Foo.propTypes = {
26 | lists: PropTypes.arrayOf(PropTypes.shape({
27 | text: PropTypes.string.isRequired
28 | }).isRequired).isRequired
29 | }
30 |
31 | // 获取state中的lists值
32 | const getList = state => {
33 | return {
34 | lists: state.update.lists
35 | }
36 | }
37 |
38 | // 利用connect将组件与Redux绑定起来
39 | export default connect(getList)(Foo)
40 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react' // 引入React
2 | import { render } from 'react-dom' // 引入render方法
3 | import { Provider } from 'react-redux' // 利用Provider可以使我们的 store 能为下面的组件所用
4 | import { Router, browserHistory } from 'react-router' // Browser history 是由 React Router 创建浏览器应用推荐的 history
5 | import { syncHistoryWithStore } from 'react-router-redux' // 利用react-router-redux提供的syncHistoryWithStore我们可以结合store同步导航事件
6 |
7 | import finalCreateStore from './src/store/configureStore' //引入store配置
8 | import DevTools from './src/containers/DevTools' // 引入Redux调试工具DevTools
9 | import reducer from './src/reducers' // 引入reducers集合
10 | import routes from './src/routes' // 引入路由配置
11 |
12 | import './assets/css/bootstrap.min.css' // 引入样式文件
13 |
14 | // 给增强后的store传入reducer
15 | const store = finalCreateStore(reducer)
16 |
17 | // 创建一个增强版的history来结合store同步导航事件
18 | const history = syncHistoryWithStore(browserHistory, store)
19 |
20 | render(
21 |
22 |
23 |
24 |
25 |
26 | ,
27 | document.getElementById('mount')
28 | )
--------------------------------------------------------------------------------
/src/containers/Home.js:
--------------------------------------------------------------------------------
1 | // 计数器
2 | import React, { Component } from 'react'
3 | import { connect } from 'react-redux'
4 | import { browserHistory } from 'react-router'
5 | import { increase, decrease } from '../actions/count'
6 |
7 | class Home extends Component {
8 | render() {
9 | const { number, increase, decrease } = this.props
10 |
11 | return (
12 |
13 |
这里显示的是当前值: {number}
14 |
15 |
16 | { ' ' }
17 |
18 | { ' ' }
19 |
20 |
21 | )
22 | }
23 | }
24 |
25 | const getNumber = state => {
26 | return {
27 | number: state.update.number
28 | }
29 | }
30 |
31 | export default connect(
32 | getNumber,
33 | { increase, decrease }
34 | )(Home)
--------------------------------------------------------------------------------
/src/containers/Bar.js:
--------------------------------------------------------------------------------
1 | // 动态数据
2 | import React, { Component } from 'react'
3 | import { connect } from 'react-redux'
4 | import { fetchPostsIfNeeded, refreshData } from '../actions/count'
5 |
6 | class Bar extends Component {
7 | render() {
8 | const { lists, fetchPostsIfNeeded, refreshData } = this.props
9 |
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 | {lists.map((e, index) =>
18 |
19 | )}
20 |
21 | )
22 | }
23 | }
24 |
25 | const getList = state => {
26 | return {
27 | lists: state.update.data
28 | }
29 | }
30 |
31 | export default connect(
32 | getList,
33 | { fetchPostsIfNeeded, refreshData }
34 | )(Bar)
35 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 |
4 | module.exports = {
5 | entry: './index.js',
6 | output: {
7 | path: path.join(__dirname, 'dist'),
8 | filename: 'bundle.js'
9 | },
10 | module: {
11 | loaders: [
12 | {
13 | test: /\.(png|jpg|gif)$/,
14 | loader: 'url-loader?limit=819200'
15 | },
16 | {
17 | test: /\.js$/,
18 | exclude: /node_modules|vue\/dist|vue-router\/|vue-loader\/|vue-hot-reload-api\//,
19 | loader: 'babel'
20 | },
21 | { test: /\.css$/,
22 | loader: 'style-loader!css-loader?sourceMap'
23 | },
24 | {
25 | test: /\.(woff|svg|eot|ttf)\??.*$/,
26 | loader: 'url-loader?limit=50000&name=[path][name].[ext]'
27 | }
28 | ]
29 | }
30 | }
31 |
32 |
33 | var src = path.join(__dirname, '..', '..', 'src')
34 | var fs = require('fs')
35 | if (fs.existsSync(src)) {
36 | module.exports.resolve = { alias: { 'react-router-redux': src } }
37 | module.exports.module.loaders.push({
38 | test: /\.js$/,
39 | loaders: ['babel'],
40 | include: src
41 | });
42 | }
43 |
--------------------------------------------------------------------------------
/src/reducers/count.js:
--------------------------------------------------------------------------------
1 | // reducers/count.js
2 | import { INCREASE, DECREASE, GETSUCCESS, REFRESHDATA } from '../constants' // 引入action类型常量名
3 |
4 | // 初始化state数据
5 | const initialState = {
6 | number: 1,
7 | lists: [
8 | {text: '整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。'},
9 | {text: '惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。'},
10 | {text: '为了描述 action 如何改变 state tree ,你需要编写 reducers。'},
11 | {text: '就是这样,现在你应该明白 Redux 是怎么回事了。'}
12 | ],
13 | data: []
14 | }
15 |
16 | // 通过dispatch action进入
17 | export default function update(state = initialState, action) {
18 |
19 | // 根据不同的action type进行state的更新
20 | switch(action.type) {
21 | case INCREASE:
22 | return Object.assign({}, state, { number: state.number + action.amount })
23 | break
24 | case DECREASE:
25 | return Object.assign({}, state, { number: state.number - action.amount })
26 | break
27 | case GETSUCCESS:
28 | return Object.assign({}, state, { data: action.json })
29 | case REFRESHDATA:
30 | return Object.assign({}, state, { data: [] })
31 | default:
32 | return state
33 | }
34 | }
--------------------------------------------------------------------------------
/src/actions/count.js:
--------------------------------------------------------------------------------
1 | import { INCREASE, DECREASE, GETSUCCESS, REFRESHDATA } from '../constants' // 引入action类型名常量
2 | import 'whatwg-fetch' // 可以引入fetch来进行Ajax
3 |
4 | // 这里的方法返回一个action对象
5 | export const increase = n => {
6 | return {
7 | type: INCREASE,
8 | amount: n
9 | }
10 | }
11 |
12 | export const decrease = n => {
13 | return {
14 | type: DECREASE,
15 | amount: n
16 | }
17 | }
18 |
19 | export const refreshData = () => {
20 | return {
21 | type: REFRESHDATA
22 | }
23 | }
24 |
25 | export const getSuccess = (json) => {
26 | return {
27 | type: GETSUCCESS,
28 | json
29 | }
30 | }
31 |
32 | function fetchPosts() {
33 | return dispatch => {
34 | return fetch('data.json')
35 | .then((res) => { console.log(res.status); return res.json() })
36 | .then((data) => {
37 | dispatch(getSuccess(data))
38 | })
39 | .catch((e) => { console.log(e.message) })
40 | }
41 | }
42 |
43 | // 这里的方法返回一个函数进行异步操作
44 | export function fetchPostsIfNeeded() {
45 |
46 | // 注意这个函数也接收了 getState() 方法
47 | // 它让你选择接下来 dispatch 什么
48 | return (dispatch, getState) => {
49 | return dispatch(fetchPosts())
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/data.json:
--------------------------------------------------------------------------------
1 | [
2 | {"title": "传统 Ajax 已死,Fetch 永生", "url": "https://segmentfault.com/a/1190000003810652"},
3 | {"title": "React官网", "url": "http://facebook.github.io/react/index.html"},
4 | {"title": "react-components", "url": "http://react-components.com/"},
5 | {"title": "React Community", "url": "https://github.com/reactjs"},
6 | {"title": "React Router 中文文档", "url": "http://react-guide.github.io/react-router-cn/index.html"},
7 | {"title": "Redux 中文文档", "url": "http://cn.redux.js.org/index.html"},
8 | {"title": "React Hot Loader", "url": "http://gaearon.github.io/react-hot-loader/"},
9 | {"title": "深入理解 react-router 路由系统", "url": "https://zhuanlan.zhihu.com/p/20381597"},
10 | {"title": "Ant Design of React", "url": "http://ant.design/docs/react/introduce"},
11 | {"title": "Vue.js中文网", "url": "http://cn.vuejs.org/"},
12 | {"title": "vue-router 中文文档", "url": "http://router.vuejs.org/zh-cn/index.html"},
13 | {"title": "vuex 中文文档", "url": "http://vuex.vuejs.org/zh-cn/index.html"},
14 | {"title": "awesome-vue", "url": "https://github.com/vuejs/awesome-vue"},
15 | {"title": "vue-resource", "url": "https://github.com/vuejs/vue-resource"},
16 | {"title": "VueStrap", "url": "http://yuche.github.io/vue-strap/"},
17 | {"title": "浅谈Vue.js", "url": "https://segmentfault.com/a/1190000004704498"},
18 | {"title": "基于Vue.js的表格分页组件", "url": "https://segmentfault.com/a/1190000005174322"}
19 | ]
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react",
3 | "version": "1.0.0",
4 | "repository": "reactjs/react-router-redux",
5 | "license": "MIT",
6 | "scripts": {
7 | "start": "webpack-dev-server --history-api-fallback --no-info --open",
8 | "build": "webpack"
9 | },
10 | "dependencies": {
11 | "antd": "^1.6.4",
12 | "bootstrap": "^3.3.6",
13 | "jquery": "^3.0.0",
14 | "react": "^0.14.7",
15 | "react-dom": "^0.14.7",
16 | "react-redux": "^4.3.0",
17 | "react-router": "^2.0.0",
18 | "react-router-redux": "^4.0.0",
19 | "redux": "^3.2.1",
20 | "redux-logger": "^2.6.1",
21 | "redux-thunk": "^2.1.0"
22 | },
23 | "devDependencies": {
24 | "babel-core": "^6.4.5",
25 | "babel-eslint": "^5.0.0-beta9",
26 | "babel-loader": "^6.2.2",
27 | "babel-plugin-antd": "^0.4.0",
28 | "babel-plugin-transform-object-assign": "^6.8.0",
29 | "babel-preset-es2015": "^6.3.13",
30 | "babel-preset-react": "^6.3.13",
31 | "babel-preset-stage-1": "^6.3.13",
32 | "css-loader": "^0.23.1",
33 | "eslint": "^1.10.3",
34 | "eslint-config-rackt": "^1.1.1",
35 | "eslint-plugin-react": "^3.16.1",
36 | "file-loader": "^0.9.0",
37 | "font-awesome": "^4.6.3",
38 | "redux-devtools": "^3.3.1",
39 | "redux-devtools-dock-monitor": "^1.1.1",
40 | "redux-devtools-log-monitor": "^1.0.11",
41 | "style-loader": "^0.13.1",
42 | "url-loader": "^0.5.7",
43 | "webpack": "^1.12.13",
44 | "webpack-dev-server": "^1.14.1",
45 | "whatwg-fetch": "^1.0.0"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/containers/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react' // 引入React
2 | import { Link } from 'react-router' // 引入Link处理导航跳转
3 |
4 | export default class App extends Component {
5 | render() {
6 | return(
7 |
8 |
31 |
32 |
33 | { this.props.children }
34 |
35 |
36 |
37 | )
38 | }
39 | }
--------------------------------------------------------------------------------
/assets/fonts/glyphicons-halflings-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/assets/fonts/glyphicons-halflings-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------