├── .babelrc
├── .gitignore
├── app
├── action.js
├── components
│ ├── about.jsx
│ ├── basic.jsx
│ ├── home.jsx
│ ├── test.jsx
│ └── topics.jsx
├── main.js
└── reducer.js
├── build
├── bundle.js
└── index.html
├── package.json
├── readme.md
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | //.babelrc
2 | {
3 | "presets": [
4 | "react",
5 | "es2015"
6 | ]
7 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/app/action.js:
--------------------------------------------------------------------------------
1 | export function increaseAction() {
2 | return {type: 'increase'};
3 | }
4 |
5 | export function multiAction() {
6 | return {type: 'multi'};
7 | }
8 |
--------------------------------------------------------------------------------
/app/components/about.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {ButtonGroup, Button} from 'react-bootstrap';
3 | class About extends React.Component {
4 | render() {
5 | return (
6 |
7 |
关于
8 |
9 |
10 |
11 |
12 |
Hello World!
13 |
14 | )
15 | }
16 | }
17 | module.exports = About;
18 |
--------------------------------------------------------------------------------
/app/components/basic.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {BrowserRouter as Router, Route, Link, Redirect, HashRouter} from 'react-router-dom'
3 | import {createBrowserHistory, createHashHistory} from 'history'
4 | const history = createHashHistory()
5 | //引入组件
6 | import Home from "./home.jsx";
7 | import Topics from "./topics.jsx";
8 | import About from "./about.jsx";
9 | import {ButtonGroup, Button} from 'react-bootstrap';
10 |
11 | import {increaseAction, multiAction} from '../action.js';
12 |
13 | import {connect} from 'react-redux';
14 |
15 | import {Tab, Tabs} from 'react-bootstrap';
16 |
17 | // React component
18 | class Basic extends React.Component {
19 | constructor(props) {
20 | super(props);
21 | // 设置 initial state
22 | this.state = {
23 | text: props.initialValue || 'Hello Wscats'
24 | };
25 | // ES6 类中函数必须手动绑定
26 | this.handleSubmit = this.handleSubmit.bind(this);
27 | }
28 | handleSubmit(event) {
29 | var page = event.target.id.charAt(event.target.id.length - 1);
30 | switch (page) {
31 | case "1":
32 | history.push('/');
33 | break;
34 | case "2":
35 | history.push('/about');
36 | break;
37 | case "3":
38 | history.push('/topics');
39 | break;
40 | }
41 | }
42 | render() {
43 | const {value, onIncreaseClick} = this.props
44 | return (
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
{value}
54 |
55 | {/*
56 | -
57 | 首页
58 |
59 | -
60 | 关于
61 |
62 | -
63 | 主题列表
64 |
65 |
*/}
66 |
67 |
68 |
69 |
70 | {/*默认跳转*/}
71 |
72 |
73 | )
74 | }
75 | }
76 |
77 | // Map Redux state to component props
78 | function mapStateToProps(state) {
79 | return {value: state.count}
80 | }
81 |
82 | // Map Redux actions to component props
83 | function mapDispatchToProps(dispatch) {
84 | return {
85 | onIncreaseClick: () => {
86 | //可以触发多个
87 | dispatch(increaseAction())
88 | dispatch(multiAction())
89 | }
90 | }
91 | }
92 | // Connected Component
93 | export default connect(mapStateToProps, mapDispatchToProps)(Basic);
94 |
--------------------------------------------------------------------------------
/app/components/home.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | class ProductBox extends React.Component {
3 | render() {
4 | return(
5 | Hello World!
6 | )
7 | }
8 | }
9 | module.exports = ProductBox;
--------------------------------------------------------------------------------
/app/components/test.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | class Test extends React.Component {
3 | render(){
4 | return (
5 | 这是一个测试组件{this.props.skill}
6 |
7 |
8 | )
9 | }
10 | onTap(){
11 | console.log("test")
12 | }
13 | }
14 | module.exports = Test;
--------------------------------------------------------------------------------
/app/components/topics.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
3 |
4 | import {connect} from 'react-redux';
5 |
6 | import {increaseAction, multiAction} from '../action.js';
7 | import Test from './test.jsx'
8 | const Topic = ({match}) => (
9 |
10 |
{match.params.topicId}
11 |
12 | )
13 | class Topics extends React.Component {
14 | render() {
15 | const {value, onIncreaseClick} = this.props;
16 | return (
17 |
18 |
主题列表
19 |
{value}
20 |
21 |
22 | -
23 |
24 | 使用 React 渲染
25 |
26 |
27 | -
28 |
29 | 组件
30 |
31 |
32 | -
33 |
34 | 属性 v. 状态
35 |
36 |
37 |
38 |
39 |
40 | (
41 | 请选择一个主题。
42 | )}/>
43 |
44 | )
45 | }
46 | }
47 |
48 | // Map Redux state to component props
49 | function mapStateToProps(state) {
50 | return {value: state.count}
51 | }
52 |
53 | // Map Redux actions to component props
54 | function mapDispatchToProps(dispatch) {
55 | return {
56 | onIncreaseClick: () => {
57 | //可以触发多个
58 | dispatch(increaseAction())
59 | dispatch(multiAction())
60 | }
61 | }
62 | }
63 |
64 | // Connected Component 让Topics也连接上store
65 | module.exports = connect(mapStateToProps, mapDispatchToProps)(Topics);
66 |
--------------------------------------------------------------------------------
/app/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import Basic from "./components/basic.jsx";
4 |
5 | //redux
6 | import {Provider, connect} from 'react-redux';
7 | import {createStore} from 'redux';
8 |
9 | //模块化action,方便在组件中调用
10 | import {increaseAction, multiAction} from './action.js';
11 | //模块化reducer
12 | import counter from './reducer.js';
13 |
14 | // Store
15 | const store = createStore(counter);
16 |
17 | // Action
18 | // const increaseAction = {
19 | // type: 'increase'
20 | // }
21 | //
22 | // const multiAction = {
23 | // type: 'multi'
24 | // }
25 |
26 | // Reducer
27 | // function counter(state = {
28 | // count: 0
29 | // }, action) {
30 | // const count = state.count
31 | // switch (action.type) {
32 | // case 'increase':
33 | // return {
34 | // count: count + 2
35 | // }
36 | // case 'multi':
37 | // return {
38 | // count: count * 2
39 | // }
40 | // default:
41 | // return state
42 | // }
43 | // }
44 |
45 | // 放在Basic入面connect
46 | // // Map Redux state to component props
47 | // function mapStateToProps(state) {
48 | // return {value: state.count}
49 | // }
50 | //
51 | // // Map Redux actions to component props
52 | // function mapDispatchToProps(dispatch) {
53 | // return {
54 | // onIncreaseClick: () => {
55 | // //可以触发多个
56 | // dispatch(increaseAction())
57 | // dispatch(multiAction())
58 | // }
59 | // }
60 | // }
61 |
62 | // Connected Component
63 | //const App = connect(mapStateToProps, mapDispatchToProps)(Basic)
64 |
65 | ReactDOM.render((
66 |
67 |
68 |
69 | ), document.getElementById('root'))
70 |
--------------------------------------------------------------------------------
/app/reducer.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {
2 | count: 0
3 | }, action) {
4 | const count = state.count
5 | switch (action.type) {
6 | case 'increase':
7 | return {
8 | count: count + 2
9 | }
10 | case 'multi':
11 | return {
12 | count: count * 2
13 | }
14 | default:
15 | return state
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React Test
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "babel-core": "6.24.1",
4 | "babel-loader": "7.0.0",
5 | "babel-preset-es2015": "6.24.1",
6 | "babel-preset-react": "6.24.1",
7 | "less-loader": "4.0.3",
8 | "react": "15.5.4",
9 | "react-dom": "15.5.4",
10 | "react-router-dom": "4.1.1",
11 | "style-loader": "0.16.1",
12 | "url-loader": "0.5.8",
13 | "webpack": "2.4.1",
14 | "webpack-dev-server": "2.4.2",
15 | "history": "4.6.1",
16 | "react-bootstrap": "0.31.0",
17 | "react-redux": "5.0.5",
18 | "react-router-config": "1.0.0-beta.3",
19 | "redux": "3.6.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # install
2 | ```bash
3 | npm install
4 | ```
5 |
6 | # run
7 | ```bash
8 | webpack-dev-server
9 | ```
10 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | //__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录
2 | module.exports = { //注意这里是exports不是export
3 | devtool: 'eval-source-map', //生成Source Maps,这里选择eval-source-map
4 | entry: __dirname + "/app/main.js", //唯一入口文件
5 | output: { //输出目录
6 | path: __dirname + "/build", //打包后的js文件存放的地方
7 | filename: 'bundle.js', //打包后的js文件名
8 | },
9 | module: {
10 | loaders: [{
11 | test: /\.js[x]?$/, //匹配到js或jsx文件后 使用 babel-loader 来处理
12 | exclude: /node_modules/, //屏蔽不需要处理的文件(文件夹)(可选)
13 | loader: 'babel-loader'
14 | //npm install babel-loader
15 | //npm install babel-core
16 | }, {
17 | test: /\.css$/,
18 | loader: 'style-loader!css-loader'
19 | }, {
20 | test: /\.less$/,
21 | loader: 'style-loader!css-loader!less-loader'
22 | }, {
23 | test: /\.(png|jpg)$/,
24 | loader: 'url-loader?limit=25000'
25 | }]
26 | },
27 | devServer: {
28 | contentBase: './build', //默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到"build"目录)
29 | historyApiFallback: true, //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
30 | inline: true, //设置为true,当源文件改变时会自动刷新页面
31 | port: 12345, //设置默认监听端口,如果省略,默认为"8080"
32 | }
33 | };
--------------------------------------------------------------------------------