這個項目標識:構建一套適合 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;