码迷,mamicode.com
首页 > 其他好文 > 详细

React

时间:2019-11-09 21:25:55      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:static   网络   span   utils   初始   logo   nod   ant   issue   

1、基础介绍
    本文采用的模块之家的实例项目为模板,采用react+react-router-dom+redux+axios+antd+js-cookie+less等技术栈来实现。
    本文假设你对react已经有基本了解。
    react官方文档
    react-router官方文档
2、创建项目
    create-react-app react_pc_demo
    cd react_pc_demo
    npm (run) start
3、暴露配置文件
    react项目默认是隐藏配置文件的。
    本项目选择暴露配置文件的方式
    npm run eject暴露配置文件(操作的时候本地不能有修改的文件、否则会报错This git repository has untracked files or uncommitted changes)
4、配置别名
    在webpack.config.js的alias配置中增加如下配置
    alias: {
      ‘@‘: paths.appSrc
    }
  
    修改引用方式,重启(修改配置文件必须重启才能生效)验证配置是否成功
    // import logo from ‘./logo.svg‘;
    // import ‘./App.css‘;
    import logo from ‘@/logo.svg‘;
    import ‘@/App.css‘;
  
5、项目结构规划
    可以修改成自己熟悉的项目结构
    +-- src/                                    ---核心代码目录
    |   +-- api                                 ---api配置
    |   +-- assets                              ---静态资源文件夹
    |   +-- components                          ---功能组件
    |   +-- layout                              ---布局组件(用于划分页面布局的组件)
    |   +-- pages                               ---页面组件(具有路由)
    |   +-- router                              ---路由配置文件
    |   +-- styles                              ---样式配置文件 
    |   +-- utils                               ---辅助函数
    |   --- index.js                            ---项目入口文件
  
    后续可根据需求进行扩展和模块划分
6、less配置
    本文采用less对css进行预处理
    npm install -S less less-loader / cnpm i -S less less-loader
  
    在webpack.config.js的style files regexes配置中增加如下配置
    const cssRegex = /\.css|less$/; 修改为=> const cssRegex = /\.css|less$/
  
    在webpack.config.js的loaders配置中增加如下配置
    {
      loader: require.resolve(‘less-loader‘)
    }
  
    修改css文件为less文件、重启服务查看效果
7、配置路由
    cnpm i -S react-router-dom // react-router-dom依赖包含react-router
    新建路由文件,在router文件下新建index.js文件
    import React from "react"
    import { HashRouter, Route, Switch, Redirect } from "react-router-dom"
    import Home from ‘@/pages/home‘
    export default () => (
      <HashRouter>
        <Switch>
          <Route path="/home" component={Home}></Route>
          <Redirect exact from="/" to="/home" />
        </Switch>
      </HashRouter>
    )
  
    在项目入口文件index.js中使用router
    import Router from "@/router"
     
    ReactDOM.render(<Router />, document.getElementById(‘root‘));
  
    路由介绍
    HashRouter/BrowserRouter 定义路由方式Hash/或者Location
    Switch路由切换组件,多个Route时用Switch包裹,否则会报警告
    Route路由
    Redirect路由重定向
    exact路由绝对匹配
8、状态管理(redux)
    cnpm i -S redux react-redux redux-thunk // redux-thunk => action异步处理
    新建store文件夹,新建state,actions,reducers,actionTypes
    state: 初始化数据
     
    import { getUserInfo } from ‘@/utils/store‘
    export default {
      userReducer: {
        userName: getUserInfo()
      },
      orderReducer: {
        orderType: ‘order‘,
        completed: ‘false‘,
        num: 0
      }
    }
  
    actionTypes: 集中管理action操作类型
     
    export const USER_LOGIN = ‘USER_LOGIN‘
    export const ADD_ORDER_NUM = ‘ADD_ORDER_NUM‘
    export const USER_LOGOUT = ‘USER_LOGOUT‘
  
    actions: 修改state必须通过action
     
    import { USER_LOGIN, ADD_ORDER_NUM, USER_LOGOUT } from ‘./actionTypes‘
    export function userLogin(payload) {
      return {
        type: USER_LOGIN,
        payload
      }
    }
    export function logout() {
      return {
        type: USER_LOGOUT
      }
    }
    export function addOrderNum() {
      return {
        type: ADD_ORDER_NUM
      }
    }
  
    reducers: 数据处理
     
    import { combineReducers } from ‘redux‘
    import { USER_LOGIN, ADD_ORDER_NUM, USER_LOGOUT } from ‘./actionTypes‘
    import initialState  from ‘./state‘
    import { setUserInfo, removeUserInfo } from ‘@/utils/store‘
    let userReducer = (state = initialState.userReducer, action) => {
      switch (action.type) {
        case USER_LOGIN:
          setUserInfo(action.payload)
          return {
            ...state,
            userName: action.payload
          }
        case USER_LOGOUT:
          removeUserInfo()
          return {
            ...state,
            userName: null
          }
        default:
          return state
      }
    }
     
    let orderReducer = (state = initialState.orderReducer, action) => {
      switch (action.type) {
        case ADD_ORDER_NUM:
          return {
            ...state,
            num: ++state.num
          }
        default:
          return state
      }
    }
     
    export default combineReducers({
      userReducer,
      orderReducer,
    })
  
    在页面中使用
    修改index.js文件
    import { createStore, applyMiddleware } from ‘redux‘
    import reducers from ‘./reducers‘
    import initialState  from ‘./state‘
    import thunk from "redux-thunk"
    const enhancer = applyMiddleware(thunk)
    export default createStore(
      reducers,
      initialState,
      enhancer
    )
  
    高阶组件connect
    // 此处仅仅只是演示页面
    import React, { Component } from ‘react‘;
    import PropsTypes from ‘prop-types‘ // cnpm i -S prop-types
    import { connect } from ‘react-redux‘ // connect高阶组件
    import { addOrderNum } from ‘@/store/actions‘ // 引入action
     
    class OrderNum extends Component {
      static PropsTypes = { // 定义数据类型
        orderType: PropsTypes.string,
        num: PropsTypes.number.isRequired,
        completed: PropsTypes.bool,
        addOrderNum: PropsTypes.func.isRequired
      }
      render() {
        return (
          <div className="order_component">
            <p>orderType: {this.props.orderType}</p>
            <p>orderNum: {this.props.num}</p>
            <p>completed: {this.props.completed}</p>
            <button onClick={this.props.addOrderNum}>add order number</button> // 使用action
          </div>
        );
      }
    }
    const mapStateToProps = (state, ownProps) => ({ // 当前组件需要使用的state数据
      orderType: state.orderReducer.orderType,
      completed: state.orderReducer.completed,
      num: state.orderReducer.num
    })
    const mapDispatchToProps = { // 当前组件需要反馈的action
      addOrderNum
    }
    export default connect(mapStateToProps, mapDispatchToProps)(OrderNum)
  
9、中间件middleware
    安装,上面已安装(可忽略)
    cnpm i -S redux-thunk // 增强action异步处理
  
    使用
      // 修改store
      import { createStore, applyMiddleware } from ‘redux‘
      import reducers from ‘./reducers‘
      import initialState  from ‘./state‘
      import thunk from "redux-thunk"
      const enhancer = applyMiddleware(thunk)
      export default createStore(
        reducers,
        initialState,
        enhancer
      )
  
10、添加布局layout和子路由
    在layout下则增加DefaultLayout组件,新增公共头部底部组件
    在router下增加module文件夹,新增frontRouter组件,在DefaultLayout使用此模块路由。
11、ui(antd)的使用
    安装依赖
    cnpm i -S antd
  
    配置, style为css和true区别你是否需要使用babel-plugin-import引入你的样式(在非按需引用时你需要将.css改为.less),它的好处在于可以显著减少包大小
    在babel-loader的plugins中增加如下配置
    [‘import‘, { libraryName: ‘antd‘, libraryDirectory: ‘es‘, style: ‘css‘ }]
    或者
    [‘import‘, { libraryName: ‘antd‘, libraryDirectory: ‘es‘, style: true }]
  
    重启后使用
    import { Button } from ‘antd‘
  
    ps,当你在使用style: true时可能遇到以下错误,Inline JavaScript is not enabled. Is it set in your options?,解决办法,在less-loader的options增加以下配置javascriptEnabled: true
    Failed to compile.
     
    ./node_modules/_antd@3.12.1@antd/es/button/style/index.less (./node_modules/_css-loader@1.0.0@css-loader??ref--6-oneOf-3-1!./node_modules/_postcss-loader@3.0.0@postcss-loader/src??postcss!./node_modules/_less-loader@4.1.0@less-loader/dist/cjs.js!./node_modules/_antd@3.12.1@antd/es/button/style/index.less)
     
    // https://github.com/ant-design/ant-motion/issues/44
    .bezierEasingMixin();
    ^
    Inline JavaScript is not enabled. Is it set in your options?
          in D:\user\80002912\桌面\my_project\react_pc_demo\node_modules\_antd@3.12.1@antd\es\style\color\bezierEasing.less (line 110, column 0)
  
    修改如下配置
    code
    {
      loader: require.resolve(‘less-loader‘),
      options: {
        javascriptEnabled: true
      }
    }
  
12、前后端交互
    安装依赖(本项目使用的是axios)
    cnpm i -S axios qs
  
    二次封装axios,详见api下index.js和fetch.js文件
    api 
      fetch.js 二次封装axios
      index.js 集中管理api,可根据需要进行模块化划分,在组件中按需引用即可
  
13、react-router路由跳转
    路由组件的跳转
    this.props.history.push(‘/path‘)
  
    外部组件的跳转
    使用Link跳转
    <Link to="/path">go to other page</Link>
  
    路由组件传递
    如test为home组件的子组件
    <test history={this.props.history} />
     
    在test中
    this.props.history.push(‘/path‘)
  
    通过context共享
    home组件
    getChildContext() { // 通过context申明共享数据
      return {
        history: createHashHistory()
      }
    }
    static childContextTypes = { // 申明共享数据类型
      history: PropTypes.object
    }
     
    在test中
    static contextTypes = { // 申明需要使用的共享数据及类型
      history: PropTypes.object
    }
    在‘render‘中通过‘this.context.history‘使用
  
    直接引用history
    import createHashHistory from ‘history/createHashHistory‘
    const history = createHashHistory()
     
    在组件内部
    history.push(‘/path‘)
  
14、组件异步加载(code split)
    react-router 4.0 以上版本
    借助babel-plugin-syntax-dynamic-import + react-loadable实现按需加载
    cnpm i -D babel-plugin-syntax-dynamic-import
    cnpm i -S react-loadable
  
    组件内使用,核心代码如下,将import Home from ‘@/pages/home‘改为使用Loadable()的方式const Home = Loadable({loader: () => import(‘@/pages/home‘), loading})
    import Loadable from ‘react-loadable‘
    import loading from ‘@/components/common/loading‘  // 自定义的loading组件
    // import Home from ‘@/pages/home‘;
    // import Login from ‘@/pages/login‘;
    // import Error_404 from ‘@/pages/error404‘;
    // import DefaultLayout from ‘@/layout/default‘;
    const Home = Loadable({loader: () => import(‘@/pages/home‘), loading});
    const Login = Loadable({loader: () => import(‘@/pages/login‘), loading});
    const Error_404 = Loadable({loader: () => import(‘@/pages/error404‘), loading});
    const DefaultLayout = Loadable({loader: () => import(‘@/layout/default‘), loading});
  
    react-router 4.0 以下版本
    借助require.ensure(),如:
    const Home = (location, cb) => {
        require.ensure([], require => {
            cb(null, require(‘./component/home‘).default);
        }, ‘home‘);
    }
    或者借助包装类‘Bundle Loader‘
    npm i --save bundle-loader
     
    const Home = (props) => (
        <Bundle load={(cb) => {
            require.ensure([], require => {
                cb(require(‘./component/home‘));
            });
        }}>
        {(Home) => <Home {...props}/>}
      </Bundle>
    );
  
    使用import(),如:
    const Home = (props) => (
        <Bundle load={() => import(‘./component/home‘)}>
            {(Home) => <Home {...props}/>}
        </Bundle>
    );
  
本文转载于网络,以资检录

 我将决定学习此框架

React

标签:static   网络   span   utils   初始   logo   nod   ant   issue   

原文地址:https://www.cnblogs.com/aibabel/p/11827827.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!