这个项目标识:构建一套适合 React、ES6 开发的脚手架
项目地址为:https://github.com/ZengTianShengZ/react-lesson
运行的是第一课,基本上能够看成是一个小型的项目,毕竟路由还有组件目录挺全的,不过,没有深刻,记一下
```html
//lesson-1/index.html
<!doctype html>
<script type="text/javascript" src="/build/static/app.js"></script>
jsx
//lesson-1/src/App.jsx
import ReactDOM, {render} from 'react-dom';
import React, {Component, PropTypes} from 'react';
import {Router,Route,hashHistory} from 'react-router';
import Main from './Component/Main.jsx'
//import Page1 from './Component/Page1.jsx'
import './Style/comm.scss'css
const Page1 = (location, cb) => {
require.ensure([], require => {
cb(null, require('./Component/Page1').default)
},'Page1')
}html
render(
document.body.appendChild(document.createElement('div'))
);java
```
node
//lesson-1/src/Component/Main.jsx import React, {Component, PropTypes} from 'react'; import {Link} from 'react-router'; class Main extends Component { constructor() { super(); } render(){ return( <div> <h1>lesson 1 </h1> <p>webpack 构建一套适合 React、ES6 开发的脚手架 </p> <Link to="/page1" activeStyle={{color: 'blue'}}>page1</Link> </div> ) } } export default Main;
//lesson-1/src/Component/page1.jsx import React, {Component, PropTypes} from 'react'; class Page1 extends Component { constructor() { super(); } render(){ return( <div> <h1>lesson 1 </h1> <p>page1</p> </div> ) } } export default Page1;
项目中的第二个例子就是老生常谈了
太冗杂了,我都不肯意去看,通常都会抽分reducer,action,storereact
//lesson-2/src/App.jsx import React,{Component,PropTypes} from 'react'; import ReactDOM, {render} from 'react-dom'; import {Provider,connect} from 'react-redux'; import {createStore, combineReducers, applyMiddleware} from 'redux'; import Index from './Component/Main.jsx'; import './Style/comm.scss' // reducer const reducer = (state = {count: 0}, action) => { switch (action.type){ case 'INCREASE': return {count: state.count + 1}; case 'DECREASE': return {count: state.count - 1}; default: return state; } } const store = createStore(reducer); //监听state变化 store.subscribe(() => { //console.log(store.getState()) }); render( <Provider store={store}> <Index></Index> </Provider>, document.body.appendChild(document.createElement('div')) );
//lesson-2/src/Component/Main.jsx import React, {Component, PropTypes} from 'react'; import {connect} from 'react-redux'; /** * 定义一个 Main组件 */ class Main extends Component{ constructor(){ super(); this.pClick =() =>{ console.log('sssssssss'); }; this.state = { num:0, age:666 } } render(){ // 拿到 this.props 参数 const {count, increase, decrease} = this.props; return( <div> <p className="lesson-2">React lesson-2</p> <p> --------------------------------- </p> <div className="count"> <div>计数:{this.props.count}次</div> <span className="btn" onClick={increase}>+</span> <span className="btn" onClick={decrease}>-</span> </div> </div> ) } } /** * 用来给 组件传递数据 * @param state */ const mapStateToProps = (state) => { return { count: state.count } }; /** *用来组件给 容器组件派发数据 * @param dispatch 派发 Action * @param ownProps 组件自身的 props参数 */ const mapDispatchToProps = (dispatch, ownProps) => { return { increase: (...args) => dispatch(actions.increase(...args)), decrease: (...args) => dispatch(actions.decrease(...args)) } }; /** * actions */ const actions ={ increase:() => { return {type: 'INCREASE'} }, decrease: () => { return {type: 'DECREASE'} } }; /** * 链接 UI组件 和 容器组件 * @param mapStateToProps 输入逻辑 * @param mapDispatchToProps 输出逻辑 */ const Comp = connect(mapStateToProps, mapDispatchToProps)(Main); /** * 输出一个容器组件 */ export default Comp;
哎,第三节也是简单的项目
不过 服务是nodejs起的webpack
//lesson-3/server.js var express = require('express'); var app = express(); var dataJson = require('./dataJson.json'); app.use(express.static('build')) /** * get: 请求 * url: http://127.0.0.1:8088/getData */ app.get('/getData',function(req,res){ var resData = { err:0, data:dataJson } res.end(JSON.stringify(resData)); }) app.get('/', function (req, res) { res.sendFile(__dirname + '/build/index.html') }) var server = app.listen(8088, function () { console.log('正常打开8088端口'); })
//lesson-3/server_hot.js var webpack = require('webpack'); var express = require('express'); var config = require('./webpack.config.hot'); var dataJson = require('./dataJson.json'); var app = express(); var compiler = webpack(config); app.use(require('webpack-dev-middleware')(compiler, { publicPath: config.output.publicPath, hot: true, historyApiFallback: true, inline: true, progress: true, stats: { colors: true, } })); app.use(require('webpack-hot-middleware')(compiler)); /** * get: 请求 * url: http://127.0.0.1:8088/getData */ app.get('/getData',function(req,res){ var resData = { err:0, data:dataJson } res.end(JSON.stringify(resData)); }) /** * 将其余路由,所有返回index.html */ app.get('/*', function(req, res) { res.sendFile(__dirname + '/index.html') }); app.listen(8088, function() { console.log('正常打开8088端口') });
//lesson-3/src/App.jsx import React,{Component,PropTypes} from 'react'; import {Provider,connect} from 'react-redux'; import ReactDOM, {render} from 'react-dom'; import store from './Redux/store' import router from './Router/router' import './Style/comm.scss' store.subscribe(() => { }); render( <Provider store={store}> {router} </Provider>, document.getElementById('root') );
//lesson-3/src/Router/router.jsx // 有用到懒加载 import React, {Component, PropTypes} from 'react'; import { Router, Route, Redirect, IndexRoute, browserHistory, hashHistory } from 'react-router'; import Index from '../Component/Index.jsx'; /*================= router.jsx 组件 专门用来管理路由的 ==================*/ /** Page2 组件按需加载 */ const page2 = (location, cb) => { require.ensure([], require => { cb(null, require('../Component/Page2').default) },'page2') } const RouteConfig =( <Router history={hashHistory}> <Route path='/' component={Index}/> <Route path='/page2' getComponent={page2}/> </Router> ) export default RouteConfig
//lesson-3/src/Component/Loading.jsx import React, {Component, PropTypes} from 'react'; import {connect} from 'react-redux'; import template from './common/template' /*================= BottonView.jsx 子组件 ==================*/ class LoadingView extends Component{ constructor(){ super(); } render(){ let{fData} = this.props; let loadingStyle; if(fData.loading){ loadingStyle = { opacity: 1 } }else{ loadingStyle = { opacity: 0 } } return( <div id='LoadingView' style={loadingStyle}> </div> ) } shouldComponentUpdate(nextProps, nextState){ return true; } } export default template({ id:'', url:'', subscribeData:['fData'], component:LoadingView })
//lesson-3/src/Redux/action.jsx import fetch from 'isomorphic-fetch' /*================= action.jsx 派发 action ==================*/ export const increase = data => { return {type: 'INCREASE',data:data} } export const decrease = data => { return {type: 'DECREASE',data:data} } const dispathData = (path,json) => { return { type: 'DISPATHDATA', path:path, json:json } } export const fetchData = (url ,data) => { return dispatch =>{ // 先派发一个 LOADING action dispatch({type:'LOADING'}); fetch(url,{ mode: 'cors', "Content-Type": "application/json" }) .then(function(response) { if (response.status >= 400) { throw new Error("Bad response from server"); } return response.json(); }) .then(function(data){ // 这里延时只是为了演示效果,实际开发中须要把延时去掉 setTimeout(function(){ // 数据请求成功 再派发一个 getData action return dispatch(dispathData('getData',data)); },3000); }) .catch(function(error) { console.log('Request failed', error) }); } }
//lesson-3/src/Redux/reducer.jsx import Immutable from 'immutable' /*================= reducer.jsx 接收Action 并做出处理 ==================*/ export const increaseData = (state =Immutable.fromJS({ count: 0}), action={}) => { switch (action.type){ case 'INCREASE': return Immutable.Map({count:action.data+1}); default: return state; } }; export const decreaseData = (state = Immutable.fromJS({ count: 8}), action={}) => { switch (action.type){ case 'DECREASE': return Immutable.Map({count:action.data-1}); default: return state; } }; export const fData = (state = {data:{},loading:false}, action={}) => { switch (action.type){ case 'LOADING': return { data:{}, loading:true }; case 'DISPATHDATA': return { data: action.json, loading:false }; default: return state; } }
//lesson-3/src/Redux/store.jsx import {createStore, combineReducers, applyMiddleware} from 'redux'; import thunk from 'redux-thunk'; import * as reducer from './reducer' /*================= store.jsx 中央数据处理器 ==================*/ var store = createStore( combineReducers(reducer), applyMiddleware(thunk) ); export default store;