• React


    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:user80002912桌面my_project eact_pc_demo ode_modules\_antd@3.12.1@antdesstylecolorezierEasing.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>
        );
      
    本文转载于网络,以资检录

     我将决定学习此框架

  • 相关阅读:
    vue2 在methods 中无法获取this对象
    mysql-set
    laravel 模板
    laravel save() 返回 null
    如何设置电脑允许远程访问并修改电脑用户密码?
    laravel报错:Unable to detect application namespace.
    b站操作系统2程序的顺序执行与并发执行
    b站计算机网络谢希仁4物理层
    b站计算机网络谢希仁2性能
    b站J数据库13之封装通用的增删改查方法
  • 原文地址:https://www.cnblogs.com/aibabel/p/11827827.html
Copyright © 2020-2023  润新知