资源:create-react-app、react、react-dom、redux、react-redux、redux-thunk、react-router-dom、antd-mobile/antd、lib(scss库)、axios/fetch
一、创建项目(首先确保你的电脑中装有create-react-app这个脚手架,如果没有,可以通过npm命令安装,或者使用后续大勋提供的项目源码)
create-react-app my-react-app
项目创建完毕,我们需要抽离配置文件,以便于可以后期合作开发
二、抽离配置文件
cd  my-react-app
cnpm run eject
 一定要选择输入y
三、项目配置
1、删除src文件夹下除了registerServiceWorker.js和index.js之外的所有的文件
2、增加components、lib(scss库)、store、router、tool、api这些文件夹
3、创建App.jsx,修改config/webpack.config.dev.js和webpack.config.prod.js,添加@符号,让它指向src目录
App.jsx
import React, {Component} from 'react'
 
export default class App extends Component {
  render () {
    return (
      <div>app</div>
    )
  }
}
 
webpack.config.dev.js的第87行
webpack.config.prod.js的第93行
 
4、在src/index.js中引入App.jsx组件,测试组件可用性,运行cnpm run start测试
import React from 'react';
import ReactDOM from 'react-dom';
import App from '@/components/App';
import registerServiceWorker from './registerServiceWorker';
 
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
 
 
5、引入错误边界异常处理,components/ErrorBoundary.jsx
import React, {Component} from 'react'
 
class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  componentDidCatch(error, info) {
    this.setState({ hasError: true });
  }
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}
 
export default ErrorBoundary
 
6、修改src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from '@/components/App';
import ErrorBoundary from '@/components/ErrorBoundary';
import registerServiceWorker from './registerServiceWorker';
 
ReactDOM.render(
  <ErrorBoundary>
    <App />
  </ErrorBoundary>
  , document.getElementById('root'));
registerServiceWorker();
 
 
7、引入scss模块
cnpm i node-sass sass-loader -D
修改config/webpack.config.dev.js和webpack.config.prod.js,添加scss的配置
webpack.config.dev.js,在191-198行写入如下代码
webpack.config.prod.js,在515-222行写入如下代码
四、创建必须组件
        因为项目中的组件我们需要将其分为容器组件和UI组件,所以此处我们先行引入react-redux模块,又因为react-redux需要redux配合使用,需要安装,如果你的项目中的组件需要有异步操作,那么需要使用到redux-thunk模块
cnpm i react-redux redux  redux-thunk -S
以首页为例,index.jsx为容器组件、ui.jsx为UI组件、store.js为该首页组件的reducer---用来提供状态
ui.jsx
import React, {Component} from 'react';
 
export default class UI extends Component {
  render () {
    return (
      <div className = "container">
        <div className = "box">页面内容</div>
        <footer>页面底部</footer>
      </div>
    )
  }
}
 
 
store.js,如果首页中有banner数据和prolist数据的话-----此处一定要记住写法
const reducer = (state = {banner: [1,2,3], prolist: []}, {type, data}) => {
  const {banner, prolist} = state;
  switch (type) {
    case 'CHANGE_BANNER':
      return {banner: data, prolist};
    case 'CHANGE_PROLIST':
        return {prolist: data, banner};;
    default:
      return state;
  }
}
 
export default reducer;
 
在src文件夹下store下的index.js
import {createStore, combineReducers} from 'redux';
 
import home from '@/components/home/store';
 
const reducer = combineReducers({home});
 
const store = createStore(reducer);
 
export default store;
 
 
在入口文件处处理index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import store from '@/store/index';
import App from '@/components/App';
import ErrorBoundary from '@/components/ErrorBoundary';
import registerServiceWorker from './registerServiceWorker';
 
ReactDOM.render(
  <Provider store = {store}>
    <ErrorBoundary>
      <App />
    </ErrorBoundary>
  </Provider>
  , document.getElementById('root'));
registerServiceWorker();
 
 
index.jsx---容器组件
import UI from './ui';
import {connect} from 'react-redux';
 
const mapStateToProps = (state) => {
  return {
    banner: state.home.banner,
    prolist: state.home.prolist
  }
}
 
const mapDispatchToProps = (dispatch) => {
  return {
 
  }
}
 
const Com = connect(
  mapStateToProps,
  mapDispatchToProps
)(UI);
 
export default Com;
 
 
如果首页UI组件内部需要在组件装载完毕之后请求数据,又不希望在容器组件内部请求数据,需要用到异步请求模块redux-thunk
UI.jsx
import React, {Component} from 'react';
 
export default class UI extends Component {
  compoentDidMount () {
    this.props.getBannerList();
    this.props.getProList();
  }
  render () {
    return (
      <div className = "container">
        <div className = "box">页面内容</div>
        <footer>页面底部</footer>
      </div>
    )
  }
}
 
新建action.js
 
const getData = (url) => {
  return new Promise((resolve, reject) => {
    fetch(url).then(res => res.json()).then(data => resolve(data)).catch(err => reject(err))
  })
}
 
export default {
  getbannerlist (dispatch) {
    getData('http://www.daxunxun.com/douban').then(data => {
      dispatch({
        type: 'CHANGE_BANNER',
        data
      })
    })
  },
  getprolist (dispatch) {
    getData('http://www.daxunxun.com/douban').then(data => {
      dispatch({
        type: 'CHANGE_PROLIST',
        data
      })
    })
  }
}
 
 
index.jsx --- 容器组件
import UI from './ui';
import {connect} from 'react-redux';
import action from './action';
import store from '@/store/index';
 
const mapStateToProps = (state) => {
//  console.log(state)
  return {
    banner: state.home.banner,
    prolist: state.home.prolist
  }
}
 
const mapDispatchToProps = (dispatch) => {
  return {
    getBannerList: () => {
//      console.log('1')
      store.dispatch(action.getbannerlist)
    },
    getProList: () => {
      store.dispatch(action.getprolist)
    }
  }
}
 
const Com = connect(
  mapStateToProps,
  mapDispatchToProps
)(UI);
 
export default Com;
 
最终,home组件结构如下
如法炮制,设置其他的一些组件,比如分类kind、购物车cart、用户中心user
 
五、设置路由模块
1、安装路由模块
cnpm i react-router-dom -S
2、创建路由模块router/index.js
import Home from '@/components/home/index';
import Kind from '@/components/kind/index';
import Cart from '@/components/cart/index';
import User from '@/components/user/index';
 
const routes = [
  {
    path: '/home',
    component: Home
  },
  {
    path: '/kind',
    component: Kind
  },
  {
    path: '/cart',
    component: Cart
  },
  {
    path: '/user',
    component: User
  }
]
 
export default routes;
 
 
3、程序入口地址修改index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import store from '@/store/index';
import App from '@/components/App';
import ErrorBoundary from '@/components/ErrorBoundary';
import registerServiceWorker from './registerServiceWorker';
import {HashRouter as Router, Switch, Route} from 'react-router-dom';
 
function render(){
  ReactDOM.render(
    <Provider store = {store}>
      <ErrorBoundary>
          <Router>
            <Switch>
              <Route path = '/' component = {App} />
            </Switch>
          </Router>
      </ErrorBoundary>
    </Provider>
    , document.getElementById('root'));
}
 
render();
 
store.subscribe(render);
 
registerServiceWorker();
 
4、修改App.jsx
import React, {Component} from 'react';
import routes from '@/router/index';
import {Switch, Route, Redirect} from 'react-router-dom';
export default class App extends Component {
  render () {
    return (
      <div>
        <Switch >
          {
            routes.map((item, index) => {
              return (
                <Route key={index} path={item.path} component = {item.component} />
              )
            })
          }
          <Redirect to={{pathname:'/home'}} /> 
        </Switch>
      </div>
    )
  }
}
 
5、地址栏输入相关路由测试可行性
6、路由跳转
    6.1 声明式跳转
        <Link>         -----  不含有样式----列表进入详情
        <NavLink>   ----- 选中的路由会自带有一个active的样式 ---- 底部切换
import {NavLink, Link} from 'react-router-dom';
 
<NavLink to='/home'>首页</NavLink><Link to='/detail/123'>详情</Link>
    6.2 编程式跳转 ---- 一定要注意写的地方
this.props.history.push('/home')
 7、假设你的项目中有一些页面结构不一致的情况下,比如说详情页面有自己的底部,那么可以在入口文件处和App组件同样配置,index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import store from '@/store/index';
import App from '@/components/App';
import Detail from '@/components/detail/index';
import ErrorBoundary from '@/components/ErrorBoundary';
import registerServiceWorker from './registerServiceWorker';
import {HashRouter as Router, Switch, Route} from 'react-router-dom';
 
function render(){
  ReactDOM.render(
    <Provider store = {store}>
      <ErrorBoundary>
          <Router>
            <Switch>
              <Route path = '/detail' component = {Detail} />
              <Route path = '/' component = {App} />
            </Switch>
          </Router>
      </ErrorBoundary>
    </Provider>
    , document.getElementById('root'));
}
 
render();
 
store.subscribe(render);
 
registerServiceWorker();
 
 
六、UI库的配置
pc:  cnpm i antd -S
mobile:  cnpm i antd-mobile -S
 
  虽然UI组件库可以全部引入,但是我们还是强烈建议使用按需引入模式
cnpm i babel-plugin-import -D
cnpm i babel-preset-env babel-preset-react -D
      创建一个.babelrc文件,写入如下内容
{
    "presets": [
        ["env", {
          "modules": false,
          "targets": {
            "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
          }
        }],
        "react"
    ],
    "plugins": [
    ["import", { "libraryName": "antd-mobile", "style": "css" }]
  ]
}
 
 
    
然后!!!最重要的一步,把package.json中的babel配置给删掉,尤其是:react-app!!!
 假设我们要使用时间选择器,需要用到模块 DatePicker
import { DatePicker, List } from 'antd-mobile';
 
<DatePicker
          value={this.state.date}
          onChange={date => this.setState({ date })}
        >
          <List.Item arrow="horizontal">Datetime</List.Item>
        </DatePicker>
        其余的UI组件类似
 
七、css的模块化
修改配置文件
webpack.config.dev.js
webpack.config.prod.js
组件内部创建style.css
UI组件内部使用
import React, {Component} from 'react';
import style from './style.css';
export default class UI extends Component {
  componentDidMount () {
    this.props.getBannerList();
    this.props.getProList();
  }
  render () {
    console.log('props', this.props)
    return (
      <div className = "container">
        <div className = {style.box}>
        <ul>
          {
            this.props.prolist.map((item,index) => {
              return (
                <li key = {item.id}>{item.title}</li>
              )
            })
          }
        </ul>
 
        </div>
        <footer>页面底部</footer>
      </div>
    )
  }
}

react 项目全家桶构件流程的更多相关文章

  1. 【React自制全家桶】六、React性能优化(持续更新总结)

    一.通过虚拟DOM来提升性能(自动) 底层讲解见[React自制全家桶]二.分析React的虚拟DOM和Diff算法   二.将多次setState合并为一次执行(自动) 底层讲解见[React自制全 ...

  2. 【React自制全家桶】九、Redux入手

    一.React项目中为什么要用Redux 上图: 左图当使用纯React开发稍微大点的项目,因为React数据是瀑布式的,只能通过父子组件传递数据,所以实现关系不大的两React的组件之间的数据传递就 ...

  3. 【React自制全家桶】七、React实现ajax请求以及本地数据mock

    一.下载axios插件 yarn add axios 二.React的ajax请求代码如何放置 建议放置在生命周期函数之componentDidMount()中 三.ajax之get请求 axios. ...

  4. 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目

    前言 一.React是Facebook推出的一个前端框架,之前被用于著名的社交媒体Instagram中,后来由于取得了不错的反响,于是Facebook决定将其开源.出身名门的React也不负众望,成功 ...

  5. 【React自制全家桶】八、React动画以及react-transition-group动画库的使用

    React动画通常有三种方法实现从易到难为: 1.transition(CSS3自带) 2.animation(CSS3自带) 3.react-transition-group动画库(需要引入插件) ...

  6. 【React自制全家桶】五、React组件的生命周期函数详解

    一.总览React组件的生命周期函数 什么是生命周期函数:简单的来说就是 在某个时刻会自动执行的函数 二.React的生命周期函数主要由四块组成 分别是:组件初始化.组件挂载.组件更新.组件卸载 三. ...

  7. 【React自制全家桶】四、React中state与props的分析与比较

    一.state 1.state的作用 state是React中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致. React中,更 ...

  8. 【React自制全家桶】三、React使用ref操作DOM与setState遇到的问题

    在React中同时使用ref操作DOM与setState常常会遇到 比如操作的DOM是setState更新之前的DOM内容,与想要的操作不一致.导致这样的原因是setState函数是异步函数. 就是当 ...

  9. 【React自制全家桶】二、分析React的虚拟DOM和Diff算法

    一.React如何更新DOM内容: 1.  获取state 数据 2.  获取JSX模版 3.  通过数据 +模版结合,生成真实的DOM, 来显示,以下行代码为例(简称代码1) <div id= ...

随机推荐

  1. Methods and Systems for Enhancing Hardware Transactions Using Hardware Transactions in Software Slow-Path

    Hybrid transaction memory systems and accompanying methods. A transaction to be executed is received ...

  2. WPF XAML中 Storyboard.TargetProperty设置TransformGroup指定的变换"RenderTransform.Children

    <Grid x:Name="xx" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransfor ...

  3. OpenCV中基于HOG特征的行人检测

    目前基于机器学习方法的行人检测的主流特征描述子之一是HOG(Histogram of Oriented Gradient, 方向梯度直方图).HOG特征是用于目标检测的特征描述子,它通过计算和统计图像 ...

  4. mingw-w64-3.10-osx10.9.sh,uninstall-macports.sh,Build NSIS on OSX

    https://gist.github.com/artynet/188bb34cfc94acdb554d283a3502770a --cross-compile-prefix=i686-w64-min ...

  5. HDU4421 Bit Magic 【2-sat】

    叙述性说明: 这给出了一个矩阵,原来的请求a排列 2-sat称号.对于每一位跑步边,跑31位可 详细的施工方 注意N=1的情况特判,还有检查对称元素是否同样 #include <stdio.h& ...

  6. 解决MacOS下readlink: illegal option -- f

    时间: 2017.03.21 分类: [操作系统] 评论 Mac下的readlink没有-f参数,诸如screenfetch又会去调用readlink -f,于是每次都会出现: readlink: i ...

  7. cocos2d-x 3.2 它 2048 —— 第三

    ***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...

  8. jquery获取选中的值和设置单选扭选中

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  9. 怎么给开源项目提PR?

    1. fork 你要的项目 2. 下载到本地 相关步骤如下 在你需要的文件夹下面,右键 git bash 命令,打开 git 命令框 执行如下指令可将项目代码下载到当前目录 ~~~ git clone ...

  10. 【Git】原Git库拆分子目录作为新仓库,并保留log记录

    一.需求描述: 现有一个git仓库,Team A和Team B的人操作同一仓库的不同目录,Team A的dev希望Team B的dev没有权限review属于Team A的代码目录,故现需要先将这个g ...