一、预备知识

  node, npm, react, redux, es6, webpack

二、学习资源

  ECMAScript 6入门

  React和Redux的连接react-redux

  Redux 入门教程   redux middleware 详解   Redux研究

  React 入门实例教程

  webpack学习demo

  NPM 使用介绍

三、工程搭建

  之前有写过 webpack+react+es6开发模式 ,文章里介绍了一些简单的配置,欢迎访问。

  1.可以npm init, 创建一个新的工程。创建package.json文件,定义需要的dependency,scripts,version等等。

  2.新增webpack.config.json文件,定义插件项配置,页面入口文件,文件输出,加载器的配置,其他解决方案配置等。下面提供了简单配置的demo,更详细的讲解,请参考  webpack 入门指南: w2bc.com/Article/50764。

  1. var webpack = require('webpack');
  2. var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
  3.  
  4. module.exports = {
  5. //插件项
  6. plugins: [commonsPlugin],
  7. //页面入口文件配置
  8. entry: {
  9. bundle: './index.js'
  10. },
  11. //入口文件输出配置
  12. output: {
  13. path: './build/',
  14. filename: '[name].js'
  15. },
  16. module: {
  17. //加载器配置
  18. loaders: [
  19. { test: /\.css$/, loader: 'style-loader!css-loader' },
  20. { test: /\.js$/, loader: 'jsx-loader?harmony' },
  21. { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
  22. { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
  23. ]
  24. },
  25. //其它解决方案配置
  26. resolve: {
  27. root: '******', //绝对路径
  28. extensions: ['', '.js', '.json', '.scss'],
  29. alias: {
  30. AppStore : 'js/stores/AppStores.js',
  31. ActionType : 'js/actions/ActionType.js',
  32. AppAction : 'js/actions/AppAction.js'
  33. }
  34. }
  35. };

  3.编写如果文件 main.js。这里创建了provider,store,history,router。实现页面的路由以及react组件以及组件间的state交互。关于react-redux内容请参考 react-redux概念理解关于react-router内容请参考 React Router 使用教程 。

  1. var React = require('react');
  2. var ReactDOM = require('react-dom');
  3. var { Provider } = require('react-redux');
  4. import { Router } from 'react-router';
  5. import routes from 'routes';
  6. import { createHashHistory, useBasename } from 'history';
  7. import { syncReduxAndRouter } from 'redux-simple-router';
  8. import { routeReducer } from 'redux-simple-router';
  9. var configureStore = require('./stores/configureStore');
  10.  
  11. // Run our app under the /base URL.
  12. const history = useBasename(createHashHistory)({
  13. basename: '/',
  14. });
  15. const store = configureStore(window.__INITIAL_STATE__);
  16.  
  17. syncReduxAndRouter(history, store);
  18.  
  19. ReactDOM.render
  20. (
  21. <Provider store={store}>
  22. <Router history={history}>
  23. {routes}
  24. </Router>
  25. </Provider>,
  26. document.getElementById('root')
  27. );

  4.创建工程的各个模块

  1. |--demo1
  2. |--src //源码
  3. |--actions // 存放当前触发Redux的动作行为
  4. |--components // 存放工程内部的公共组件
  5. |--modules // 存放工程各模块代码
  6. |--constants   // action动作常量
  7. |--reducers // 存放reducer函数,用来修改store状态
  8. |--routes // 放置页面路由 react router
  9. |--stores // 放置stores配置文件
  10. |--main.js // 入口js
  11. |--index.html // 工程入口文件html
  12. |--node_modules // 存放依赖的第三方模块库,使用命令 npm install
  13. |--build //打包文件存放的目录
  14. |--webpack.config.js
  15. |--package.json

四、功能开发

  1.做一个简单的Home页面

  (1).在modules文件夹新建Home.js, 使用antd 的Menu组件, 展示我们要演示的功能。

  1. import React from 'react';
  2. import 'less/home.less';
  3. import { Scrollbars } from 'react-custom-scrollbars';
  4. import {Menu} from 'antd';
  5.  
  6. //首页
  7. export class Home extends React.Component{
  8. constructor(props) {
  9. super(props);
  10. this.changeRoute = this.changeRoute.bind(this);
  11. }
  12. componentDidMount() {
  13. }
  14.  
  15. changeRoute(e) {
  16. this.context.history.pushState({}, e.key);
  17. }
  18.  
  19. render() {
  20. return (
  21. <div className='home'>
  22. <Scrollbars style={{ height: 600 }}>
  23. <Menu className='menu' onClick={this.changeRoute}>
  24. <Menu.Item key='showSelfMsg'>页面渲染展示信息</Menu.Item>
  25. <Menu.Item key='frontAndRearInteractive'>模拟前后台交互</Menu.Item>
  26. <Menu.Item key='pageExchange'>页面切换</Menu.Item>
  27. <Menu.Item key='extend'>子组件扩展</Menu.Item>
  28. </Menu>
  29. </Scrollbars>
  30. </div>
  31. );
  32. }
  33. }
  34. Home.contextTypes = {
  35. history: React.PropTypes.object.isRequired,
  36. };
  37. module.exports = Home;

  (2).注册Home页面的路由,对应routes/index.js加入如下代码。

  1. <Route path="/" component={ModuleRouters}>
  2. <IndexRoute component={Home} />
  3. </Route>

  (3).启动工程, npm run dev, 浏览器中输入 http://localhost:8000/demo1,即可预览我们的Home页面。

  

  2.单页面渲染,完成数据的展示和隐藏

  (1).在component目录下新建ShowSelfMsg.js, 通过改变state状态,重新渲染页面.

  1. import React from 'react';
  2. import {connect} from 'react-redux';
  3. import {Button} from 'antd';
  4. import 'less/common.less';
  5. var mapStateToProps = function(state){
  6.  
  7. };
  8.  
  9. class ShowSelfMsg extends React.Component{
  10. constructor(props){
  11. super(props);
  12. this.state = {
  13. showContent: false
  14. };
  15. this.showContent = this.showContent.bind(this);
  16. }
  17.  
  18. showContent() {
  19. this.setState({
  20. showContent: !this.state.showContent
  21. });
  22. }
  23.  
  24. componentDidMount() {
  25. const { dispatch} = this.props;
  26. //加载该页面的数据
  27. }
  28.  
  29. componentWillReceiveProps(nextProps) {
  30. }
  31.  
  32. render() {
  33. let showContent = this.state.showContent;
  34. return (
  35. <div className='main'>
  36. <div className='content'>
  37. <Button type="ghost" onClick={this.showContent}>{!this.state.showContent ? '单击显示内容' : '单击隐藏内容'}</Button>
  38. {
  39. showContent ? (<div><span>大家好,我是hjzgg</span></div>) : (null)
  40. }
  41. <div className='back'>
  42. <Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button>
  43. </div>
  44. </div>
  45. </div>
  46. );
  47. }
  48. }
  49.  
  50. ShowSelfMsg.contextTypes = {
  51. history: React.PropTypes.object.isRequired,
  52. };
  53. module.exports = connect(mapStateToProps)(ShowSelfMsg);

  (2).注册路由,在routes/index.js中加入如下代码。

  1. <Route path="/showSelfMsg" component={ShowSelfMsg} />

  (3).在Home页面中点击 ‘页面渲染展示信息’,即可进入这个页面。

  

  3.模拟前后台交互

  (1).代码编写如下。

    (I).在constants新建ActoinTypesjs,定动作类型;

    (II).在actions目录中新建simulationRquest.js, 定义要分发的动作;

    (III)在reducers目录新建simulationRquest.js,存放reducer函数,用来修改store状态,然后将该函数放入到reducers/index.js中的combineReducers函数中,最终会合并成一个新的reducer;

    (IV)components目录中新建FrontAndRearInteractive.js, dispatch 自定义的动作,实现模拟前后台交互功能。

  ActionType.js

  1. export const SIMULATION_REQUEST_SUCCESS = 'SIMULATION_REQUEST_SUCCESS';
  2. export const SIMULATION_REQUEST_FAIL = 'SIMULATION_REQUEST_FAIL';
  3. export const INIT_EXTEND_DATA_SUCCESS = 'INIT_EXTEND_DATA_SUCCESS';
  4. export const INIT_EXTEND_DATA_FAIL = 'INIT_EXTEND_DATA_FAIL';
  5. export const SAVE_EXTEND_DATA_SUCCESS = 'SAVE_EXTEND_DATA_SUCCESS';

  FrontAndRearInteractive.js

  1. import React from 'react';
  2. import {connect} from 'react-redux';
  3. import {Button} from 'antd';
  4. import {simulationRquestAction} from 'actions/simulationRequest';
  5. var mapStateToProps = function(state){
  6. return {
  7. myRequest: state.myRequest,
  8. }
  9. };
  10.  
  11. class FrontAndRearInteractive extends React.Component{
  12. constructor(props){
  13. super(props);
  14. this.state = {
  15. showContent: false
  16. };
  17. this.simulationRequest = this.simulationRequest.bind(this);
  18. }
  19.  
  20. simulationRequest() {
  21. const {dispatch} = this.props;
  22. console.log('props>>>dispath:' + dispatch);
  23. dispatch(simulationRquestAction());
  24. }
  25.  
  26. componentDidMount() {
  27. const { dispatch} = this.props;
  28. //加载该页面的数据
  29. }
  30.  
  31. componentWillReceiveProps(nextProps) {
  32. const { myRequest } = nextProps;
  33. if(myRequest.code && myRequest.msg)
  34. alert('请求结果:code=' + myRequest.code + ', msg=' + myRequest.msg);
  35. }
  36.  
  37. render() {
  38. const { myRequest } = this.props;
  39. return (
  40. <div className='main'>
  41. <div className='content'>
  42. <Button type="ghost" onClick={this.simulationRequest}>模拟请求</Button>
  43. {
  44. myRequest && myRequest.data ? (<div><span>{myRequest.data}</span></div>) : (null)
  45. }
  46. <div className='back'>
  47. <Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button>
  48. </div>
  49. </div>
  50. </div>
  51. );
  52. }
  53. }
  54. FrontAndRearInteractive.contextTypes = {
  55. history: React.PropTypes.object.isRequired,
  56. };
  57. module.exports = connect(mapStateToProps)(FrontAndRearInteractive);

  actions/simulationRquest.js

  1. import {ajax} from 'utils/ajax';
  2. import url from 'utils/Url';
  3. import {
  4. SIMULATION_REQUEST_SUCCESS, SIMULATION_REQUEST_FAIL,
  5. } from 'constants/ActionTypes';
  6.  
  7. function simulationRquestSuccess(data, msg){
  8. return {
  9. type: SIMULATION_REQUEST_SUCCESS,
  10. data,
  11. msg,
  12. }
  13. }
  14.  
  15. function simulationRquestFail(msg){
  16. return {
  17. type: SIMULATION_REQUEST_FAIL,
  18. msg,
  19. }
  20. }
  21.  
  22. export function simulationRquestAction(args){
  23. return function (dispatch) {
  24. console.log('actions>>>dispath:' + dispatch);
  25. /*
  26. //真是请求
  27. ajax({
  28. method : 'GET',
  29. url : url.QUERY_ALL_USER,
  30. query : {'args': args},
  31. type : 'json',
  32. success : function(data) {
  33. return dispatch(simulationRquestSuccess(data));
  34. },
  35. error : function(data) {
  36. return dispatch(simulationRquestFail('request fail'));
  37. }
  38. });
  39. */
  40. //假设请求成功
  41. return dispatch(simulationRquestSuccess('我是后台返回数据:hjzgg!!!', '获取数据成功'));
  42. };
  43. }

  reducers/simulationRquest.js

  1. import {
  2. SIMULATION_REQUEST_SUCCESS, SIMULATION_REQUEST_FAIL,
  3. } from 'constants/ActionTypes';
  4. import assign from 'lodash/assign';
  5.  
  6. function myRequest(state = {
  7. data: null,
  8. msg: null,
  9. code: null,
  10. }, action) {
  11. console.log('reducer action属性>>>>>' + JSON.stringify(action));
  12.  
  13. switch(action.type) {
  14. case SIMULATION_REQUEST_SUCCESS:
  15. return assign({}, state, {
  16. msg: action.msg,
  17. data: action.data,
  18. code: 'success',
  19. });
  20.  
  21. case SIMULATION_REQUEST_FAIL:
  22. return assign({}, state, {
  23. msg: action.msg,
  24. data: null,
  25. code: 'fail',
  26. });
  27. default:
  28. return state;
  29. }
  30.  
  31. }
  32.  
  33. module.exports = myRequest;

  (2).路由注册,在routes/index.js增加如下代码。

  1. <Route path="/frontAndRearInteractive" component={FrontAndRearInteractive} />

  (3).在Home页面中点击 ‘模拟前后台交互’,即可进入页面。

  

  4.页面切换

  (1).在components目录新建PageExchange.js 和 Childpage.js,分别为父页面和子页面。注意,这里父页面的变量信息 是通过路由的方式传递过去的,当然也可以通过state方式传递过去。

  PageExchange.js

  1. import React from 'react';
  2. import {connect} from 'react-redux';
  3. import {Button} from 'antd';
  4. import 'less/common.less';
  5. var mapStateToProps = function(state){
  6.  
  7. };
  8.  
  9. class PageExchange extends React.Component{
  10. constructor(props){
  11. super(props);
  12. this.state = {
  13. showContent: false
  14. };
  15. this.gotoChildPage = this.gotoChildPage.bind(this);
  16. }
  17.  
  18. gotoChildPage() {
  19. console.log('this.context.history>>>>>>' + JSON.stringify(this.context.history));
  20. this.context.history.pushState({}, 'childDemoPage/' + '我是父页面信息');
  21. }
  22.  
  23. componentDidMount() {
  24. const { dispatch} = this.props;
  25. //加载该页面的数据
  26. }
  27.  
  28. componentWillReceiveProps(nextProps) {
  29. }
  30.  
  31. render() {
  32. let showContent = this.state.showContent;
  33. return (
  34. <div className='main'>
  35. <div className='content'>
  36. <Button type="ghost" onClick={this.gotoChildPage}>进入子页面</Button>
  37. <div className='back'>
  38. <Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button>
  39. </div>
  40. </div>
  41. </div>
  42. );
  43. }
  44. }
  45.  
  46. PageExchange.contextTypes = {
  47. history: React.PropTypes.object.isRequired,
  48. };
  49. module.exports = connect(mapStateToProps)(PageExchange);

  Childpage.js

  1. import React from 'react';
  2. import {connect} from 'react-redux';
  3. import {Button} from 'antd';
  4. import 'less/common.less';
  5. var mapStateToProps = function(state){
  6. return {
  7. }
  8. };
  9.  
  10. class ChildPage extends React.Component{
  11. constructor(props){
  12. super(props);
  13. this.returnParentPage = this.returnParentPage.bind(this);
  14. }
  15.  
  16. componentDidMount() {
  17. const { dispatch} = this.props;
  18. //加载该页面的数据
  19. }
  20.  
  21. componentWillReceiveProps(nextProps) {
  22. }
  23.  
  24. returnParentPage() {
  25. this.context.history.pushState(null, 'pageExchange');
  26. }
  27.  
  28. render() {
  29. const parentPageMsg = this.props.params.parentPageMsg;
  30. return (
  31. <div className='main'>
  32. <div className='content'>
  33. <Button type="ghost" onClick={this.returnParentPage}>返回父页面</Button>
  34. {
  35. parentPageMsg ? (<div><span>{parentPageMsg}</span></div>) : (null)
  36. }
  37. </div>
  38. </div>
  39. );
  40. }
  41. }
  42.  
  43. ChildPage.contextTypes = {
  44. history: React.PropTypes.object.isRequired,
  45. };
  46. module.exports = connect(mapStateToProps)(ChildPage);

  (2).注册路由,在routes/index.js中加入如下代码。

  1. <Route path="/pageExchange" component={PageExchange} />
  2. <Route path="/childDemoPage(/:parentPageMsg)" component={ChildPage}/>

  (3).在Home页面中点击‘页面切换’,即可进入页面。

  

  5.自定义扩展组件

  (1).先说一下应用场景:多个页面可能需要类似的扩展功能,通过自定义扩展组件,完成对信息的加载。主页面信息保存时,通知扩展组件要保存信息了,扩展组件将最新修改的信息告知主页面,主页面获取到全部信息后,一起将数据传给后台,完成主页面信息和扩展信息的保存。

  (2).在components目录下新建Page.js和ExtendPage.js,分别为主页面和自定义扩展组件。

  Page.js

  1. import React from 'react';
  2. import {connect} from 'react-redux';
  3. import {Button, Input, Form} from 'antd';
  4. import ExtendPage from 'components/ExtendPage';
  5. import 'less/common.less';
  6. const FormItem = Form.Item;
  7. var mapStateToProps = function(state){
  8. return {
  9. extendStore: state.extendStore
  10. }
  11. };
  12.  
  13. class Page extends React.Component{
  14. constructor(props){
  15. super(props);
  16. this.state = {
  17. childState: false,
  18. }
  19. this.handleSubmit = this.handleSubmit.bind(this);
  20. this.onSaveExtendPage = this.onSaveExtendPage.bind(this);
  21. }
  22.  
  23. componentDidMount() {
  24. const { dispatch} = this.props;
  25. //加载该页面的数据
  26. }
  27.  
  28. componentWillReceiveProps(nextProps) {
  29. }
  30.  
  31. //通知扩展组件,准备保存了
  32. onSaveExtendPage() {
  33. if(this.state.childState) {
  34. this.setState({
  35. childState: false,
  36. });
  37. }
  38. }
  39.  
  40. save(values) {
  41. //打印父级和子级文本
  42. alert(JSON.stringify(values));
  43. }
  44.  
  45. handleSubmit() {
  46. var self = this;
  47. this.props.form.validateFields((err, values) => {
  48. if (!err) {//表单符合标准
  49. //values 为当前父页面的数据,接下来获取子页面的数据
  50. this.setState({childState: true}, function() {
  51. const { extendStore } = self.props;
  52. values.extendData = extendStore && extendStore.data || extendStore;
  53. self.save(values);
  54. });
  55. }
  56. });
  57. }
  58.  
  59. render() {
  60. const { getFieldProps } = this.props.form;
  61. const inputProps = getFieldProps('inputText', {
  62. initialValue: '',
  63. rules: [
  64. {required: true, message: 'the input is required' },
  65. ],
  66. validateTrigger: "onBlur"
  67. });
  68. return (
  69. <div style={{marginTop: 50, width: 600, marginLeft: 'auto', marginRight: 'auto'}}>
  70. <Form onSubmit={this.handleSubmit}>
  71. <FormItem {...{labelCol: { span: 6 }, wrapperCol: { span: 14 }}} label="父级文本: ">
  72. <Input {...inputProps} id='inputText' type='text'/>
  73. </FormItem>
  74. <FormItem wrapperCol={{ span: 12, offset: 6 }}>
  75. <Button type="primary" htmlType="submit">提交</Button>
  76. </FormItem>
  77. </Form>
  78.  
  79. <ExtendPage
  80. childState={this.state.childState}
  81. callBack={this.onSaveExtendPage}
  82. />
  83.  
  84. <div style={{float: 'right'}}>
  85. <Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button>
  86. </div>
  87. </div>
  88. );
  89. }
  90. }
  91. Page.contextTypes = {
  92. history: React.PropTypes.object.isRequired,
  93. };
  94. Page = Form.create()(Page);
  95. module.exports = connect(mapStateToProps)(Page);

  ExtendPage.js

  1. import React from 'react';
  2. import {connect} from 'react-redux';
  3. import {Button, Form, Input, message} from 'antd';
  4. const FormItem = Form.Item;
  5. import {initExtendData, saveExtendDataAction} from 'actions/extendPage';
  6. var mapStateToProps = function(state){
  7. return {
  8. extendStore: state.extendStore
  9. }
  10. };
  11.  
  12. class ExtendPage extends React.Component{
  13. constructor(props){
  14. super(props);
  15. this.state = {
  16.  
  17. }
  18.  
  19. this.saveExtendData = this.saveExtendData.bind(this);
  20. this.checkText = this.checkText.bind(this);
  21. }
  22.  
  23. checkText(rule, value, callBack) {
  24. if(/\s+/.test(value)) {
  25. callBack("不能有空白字符");
  26. } else {
  27. callBack();
  28. }
  29. }
  30.  
  31. saveExtendData() {
  32. this.props.callBack();//保存成功后,更改父页面的childState的状态
  33. this.props.form.validateFields((err, values) => {
  34. if (!err) {//表单符合标准
  35. console.log('save ExtendPage values: ' + JSON.stringify(values));
  36. const {dispatch} = this.props;
  37. dispatch(saveExtendDataAction(values));
  38. }
  39. });
  40. }
  41.  
  42. componentDidMount() {
  43. const { dispatch} = this.props;
  44. //初始化扩展页的数据
  45. dispatch(initExtendData());
  46. }
  47.  
  48. componentWillReceiveProps(nextProps) {
  49. const { extendStore, childState } = nextProps;
  50. if(extendStore && extendStore.msg) {
  51. message.info(extendStore.msg, 5);
  52. extendStore.msg = null;
  53. }
  54.  
  55. if(childState) {//父页面 改变 子页面的状态
  56. this.saveExtendData();
  57. }
  58. }
  59.  
  60. render() {
  61. const { getFieldProps } = this.props.form;
  62. const { extendStore } = this.props;
  63. const inputValue = extendStore && extendStore.data && extendStore.data.extendInputText || null;
  64. const inputProps = getFieldProps('extendInputText', {
  65. initialValue: inputValue,
  66. rules: [
  67. {required: true, message: 'the input is required' },
  68. {validator: this.checkText}
  69. ],
  70. validateTrigger: "onBlur"
  71. });
  72. return (
  73. <div>
  74. <Form>
  75. <FormItem {...{labelCol: { span: 6 }, wrapperCol: { span: 14 }}} label="扩展本文: ">
  76. <Input {...inputProps} type="text" id="extendInputText"/>
  77. </FormItem>
  78. </Form>
  79. </div>
  80. );
  81. }
  82. }
  83. ExtendPage = Form.create()(ExtendPage);
  84. module.exports = connect(mapStateToProps)(ExtendPage);

  (3).说一下组件的扩展机制

  (I).扩展组件自身会维护更新自己state状态,在触发扩展组件保存时,扩展组件将自身数据通过dispatch进行分发,最后通过对应的reducer(这个reducer会通过combineReducers函数合并成一个新的reducer)进行处理,根据逻辑生成新的state。

  >>定义动作类型

  

  >>分发动作

  

  >>reducer处理动作,返回新的state

  

  >>自定义的reducer函数通过combineReducers函数进行合并

  

  (II).父级组件如何获取扩展组件的状态?

  

  也就是store中的状态树变化的时候,组件可以通过 mapStateToProps 函数从状态树中获取最新的state。

  (III).父级组件如何通知扩展组件 准备保存数据了?

  

  >>扩展组件接收父级组件两个参数:childState, 通知扩展组件状态发生变化; callBack, 修改childState状态,扩张组件通知父级组件更新完成。

  

  >>父级组件保存数据时,首先获取到自己的数据,然后通过setState()方法改变childState的值,通知扩展组件。最后通过setState方法传入的回调函数(该函数在组件更新完成之后调用)获取到扩展组件的最新state。

  

  

  >>扩展组件接收到父级组件的通知,刷新store中的state。这样父级组件和扩展组件自身都可以通过mapStateToProps方法获取到最新的state。

  (4).注册路由,在routes/index.js中加入如下代码。

  

  (5).在Home页面中点击‘页面切换’,即可进入页面。

    

五、问题解惑

   1.module.filename、__filename、__dirname、process.cwd():  http://www.tuicool.com/articles/bQre2a
   2.node.js之path模块: http://www.jianshu.com/p/fe41ee02efc8
   3.react-router: http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu
     4.出现如下错误:Cannot sync router: route state does not exist. Did you install the routing reducer,参考:

    http://stackoverflow.com/questions/34039619/redux-simple-router-react-router-error-route-state-does-not-exist

  5.module.exprots, export, export default区别:

  1. export default variation
  2.  
  3. import variation from 'js file'
  4.  
  5. export variation
  6.  
  7. import {variation} from 'js file'
  8.  
  9. module.exports=variation
  10.  
  11. import variation from 'js file'

  参考:

  http://www.2cto.com/kf/201412/360211.html

  http://www.jb51.net/article/33269.htm

  http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632

  http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632

六、完整项目下载

  https://github.com/hjzgg/webpack-react-redux

 
 
 

webpack+react+redux+es6的更多相关文章

  1. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  2. webpack+react+redux+es6开发模式---续

    一.前言 之前介绍了webpack+react+redux+es6开发模式 ,这个项目对于一个独立的功能节点来说是没有问题的.假如伴随着源源不断的需求,前段项目会涌现出更多的功能节点,需要独立部署运行 ...

  3. 使用 webpack + react + redux + es6 开发组件化前端项目

    因为最近在工作中尝试了 webpack.react.redux.es6 技术栈,所以总结出了一套 boilerplate,以便下次做项目时可以快速开始,并进行持续优化.对应的项目地址:webpack- ...

  4. react案例->新闻移动客户端--(react+redux+es6+webpack+es6的spa应用)

    今天分享一个react应用,应在第一篇作品中说要做一个react+redux+xxx的应用.已经做完一部分,拿出来分享.github地址为:点我就可以咯~ 这里实现了一个新闻移动站的spa.本来想写p ...

  5. 6周学习计划,攻克JavaScript难关(React/Redux/ES6 etc.)

    作者:余博伦链接:https://zhuanlan.zhihu.com/p/23412169来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 和大家一样,最近我也看了Jo ...

  6. 如何从零搭建一个webpack+react+redux+react-redux的开发环境一入门

    阅读本文章的时候,你要有一定的基础知识储备,简单的es6知识,模块化思想知识,js基础知识,node基础知识,react等 首先执行npm init,此时我的文件叫case; 下面安装一些需要的npm ...

  7. webpack+react+es6开发模式

    一.前言 实习了两个月,把在公司用到的前端开发模式做个简单的整理.公司里前端开发模式webpack+react+redux+es6,这里去掉了redux. webpack, react, redux等 ...

  8. 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用

    先看效果图 github地址 github仓库 在线访问 初始化项目 #创建项目 create-react-app applist #如果没有安装create-react-app的话,先安装 npm ...

  9. Webpack+React+ES6开发模式入门指南

    React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...

随机推荐

  1. Volley网络连接

    一.Volley a burst or emission of many things or a large amount at once Volley是Android平台上的网络通信库,能使网络通信 ...

  2. 【原】error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::string'

    今天遇到一个非常难以排查的BUG,谷歌度娘都问过了依旧无解,最后自己重新尝试之后找到解决方案: 先看一下报错信息: 1>.\lenz.cpp(2197)  error C2679: binary ...

  3. XtraScheduler 日程控件显示自定义标题

    下面代码实现一个自定义日程标题 public class CustomHeaderCaptionService : HeaderCaptionServiceWrapper { public Custo ...

  4. Effetive Java 22 Favor static member classes over nonstatic

    Nested class types Usage and remark Advantage Disadvantage static member classes Use for public help ...

  5. JavaScript Patterns 4.4 Self-Defining Functions

    If you create a new function and assign it to the same variable that already holds another function, ...

  6. 【SQL查询】集合查询之INTERSECT

    [SQL查询]集合查询之INTERSECT 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~ ...

  7. 【php】mysql全局ID生成方案

    生产系统随着业务增长总会经历一个业务量由小变大的过程,可扩展性是考量数据库系统高可用性的一个重要指标;在单表/数据库数据量过大,更新量不断飙涨时,MySQL DBA往往会对业务系统提出sharding ...

  8. 问题解决——XP线程池找不到QueueUserWorkItem

    2013年7月11号 主管让同事写一个并发100的小工具进行什么压力测试,据说是创建100个线程. 我表示这真真的是在坑人! 线程创建消耗资源,以自己的笔记本来跑这个东西,时间片都消耗在了线程切换上了 ...

  9. 设计模式C#实现(五)——抽象工厂模式

    抽象工厂模式 意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类. UML类图: 场景:抽象村商店想销售Pizza和Hamburg等多种商品,而在美国店和中国店要出售本土化的口味 ...

  10. pushd

    # MAN 手册原文:        pushd [-n] [+n] [-n]        pushd [-n] [dir]               Adds  a  directory to ...