美文网首页
create-react-app搭建一个完整的项目

create-react-app搭建一个完整的项目

作者: Issho | 来源:发表于2019-10-09 14:25 被阅读0次

    ☼ 注:笔者的文章是根据自己当前项目做的笔记,具体应用请参照自己实际项目情况

    1、创建应用
    npx create-react-app my-app
    cd my-app
    npm start
    
    2、热加载,src/index.js文件
    function render() {
        ReactDOM.render(
            <App />,
            document.getElementById('root'))
    }
    
    render()
    
    if (module.hot) {
        module.hot.accept(() => {
            render()
        })
    }
    
    3、配置eslint代码规范

    ⑴ 在根目录新建.eslintrc.js文件

    const pkg = require('./package.json')
    const reactVersion = () => {
        if (pkg.dependencies && pkg.dependencies.react) {
            return { version: pkg.dependencies.react.replace(/[^0-9.]/g, '') }
        }
        if (pkg.devDependencies && pkg.devDependencies.react) {
            return { version: pkg.devDependencies.react.replace(/[^0-9.]/g, '') }
        }
    }
    
    module.exports = {
        "parser": "babel-eslint",
        // 配置规则
        "rules": {
            "strict": 0,
            "no-console": 0,
            "global-require": 0,
            "jsx-a11y/href-no-hash": 0,
            "react/forbid-prop-types": 0,
            "jsx-a11y/no-static-element-interactions": 0,
            'import/no-dynamic-require': 0,
            "import/no-extraneous-dependencies": 0,
            "max-len": ["error", 240],
            "linebreak-style":0,
            "no-eval": 2,
            "indent": ["error", 4, { "SwitchCase": 1 }],
            "no-tabs": 0,
            "comma-dangle": 0,
            "no-array-index-key": 0,
            "arrow-parens": 0,
            "object-shorthand": 0,
            "react/jsx-filename-extension": 0,
            "react/jsx-indent": 0,
            "react/jsx-indent-props": 0,
            "react/require-default-props": 0,
            "react/no-array-index-key": 0,
            "no-prototype-builtins": 0,
            "no-continue": 0,
            "no-restricted-globals": [0],
            "quotes": ["error", "single"],
            "keyword-spacing": ["error", { "before": true }],
            "no-var": 1,
            "semi": ["error", "never"],
            "key-spacing": ["error", {  "afterColon": true }],
            "comma-spacing": ["error", { "before": false, "after": true }],
            "arrow-spacing": ["error", { "before": true, "after": true }],
            "no-multi-spaces": ["error"],
            "no-trailing-spaces": ["error", { "skipBlankLines": true }],
        },
        "env": {
            "browser": true,
            "node": false
        },
        "plugins": [
            "react",
            "jsx-a11y",
            "import"
        ],
        "globals": {
            "DEBUG": false,
            "NORMAL_SERVER": true,
            "CUSTOMER_FLAG": true,
            "IS_USE_NATIVE_CAMERA": true,
            "TOMCAT_SERVER_SIGN_ADDRESS": true,
            "TOMCAT_SERVER_ACCOUNT_HINT_ADDRESS": true,
            "UPLOAD_IMG_OVER_TIME": true,
            "IS_NEED_CREATE_HISTORY": true,
        },
        'settings': {
            'react': {
                ...reactVersion()
            }
        }
    }
    

    ⑵ 打开【文件】→【首选项】→【设置】→【用户】或【工作区】→【扩展】→【ESLint】→【setting.json】,添加以下代码

    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact"
    ],
    

    (3) 在【用户】→【扩展】→【ESLint】把【Auto Fix On Save】勾上,就可以在保存代码时自动修复eslint警告了
    ⑷ 配置eslint检查忽略的文件路径,在根目录新建.eslintignore文件

    # product path
    build
    
    # lib path
    node_modules
    config
    scripts
    
    

    ☆ 以上配置步骤针对vscode,并且确保已经安装了【ESLint】插件

    4、异步加载组件

    见笔者文章《react异步加载组件

    5、配置axios

    ⑴ 安装

    npm install axios --save
    npm install qs --save
    

    ⑵ 在src目录下新建api目录,在api目录下新建一个axios.js文件用于配置axios拦截器
    ⑶ 在api目录下新建一个config.js

    export const HOST = window.location.origin
    // 不同环境
    export const apiUrl = HOST.includes('cms') ? 'v1/xxx' : 'c/xxx'
    

    ⑷ 把项目中需要用到的接口按模块划分,分别新建一个js文件

    import axios from '../axios'
    import { apiUrl } from '../config'
    
    export default {
        /***
         * 登录检查
         * @method post
         * @return  JSON  data :{"username":account,"password":devpasword};
         *  */
        loginCheck: data => axios.post(apiUrl+'/common/admin/loginCheck.do', data),
    
        /***
         * 登录
         * @method post
         * @return  JSON  data :{};
         *  */
        login: data => axios.get(apiUrl+'/admin/login.do', data),
    }
    
    6、配置proxy跨域代理

    见笔者文章《create-react-app和vue-cli配置跨域代理

    7、代理到本地mock数据

    ⑴ 在config文件夹下新建一个mock.js(名字无所谓,自己起)

    const glob = require('glob')
    const fs = require('fs')
    
    const files = glob.sync('mock/**/*.json')
    
    module.exports = function (app) {
        files.forEach(file => {
            let data = fs.readFileSync('./' + file, 'utf8')
            app.all(file.slice(4, -5), (req, res) => {
                console.log('req', req.originalUrl)
                res.setHeader('Access-Control-Allow-Origin', '*')
                res.setHeader('Access-Control-Allow-Methods', 'DELETE,GET,HEAD,POST,PUT,OPTIONS,TRACE')
                res.setHeader("Access-Control-Allow-Headers", "X-Custom-Header,accept, Content-Type")
                res.setHeader('Access-Control-Allow-Credentials', 'true')
                res.setHeader('Content-Type', 'application/json;charset=UTF-8')
                res.status(200).send(data)
            })
        })
    }
    

    ⑵ 在webpackDevServer.config.js文件中,找到before函数,引入mock.js

    before(app, server) {
        // 当使用mock数据的时候打开
        require('./mock.js')(app)
    }
    

    ⑶ 在项目的根目录下【注意是根目录,不是src目录】,新建一个mock文件夹,然后在mock文件夹下按照接口地址新建一个json文件,把模拟的数据写在json文件里即可,例如:

    接口地址为:'/clife-estate-api-web-admin/estate/menuMgr/queryMenuResource.do'
    文件目录为:'mock/clife-estate-api-web-admin/estate/menuMgr/queryMenuResource.do.json'
    数据内容为:
    {
        "data": {
            "record": [],
            "totalRows": 0
        },
        "code": 0
    }
    

    ⑷ 每次添加mock数据后,重新启动项目, 项目启动默认是走mock数据,如果没有mock数据的就走后台接口

    8、配置mobx

    见笔者文章《create-react-app中配置less和mobx
    ⑴ 在src目录下新建一个store目录,在store目录下按大模块划分文件夹,再按小模块分别新建一个文件用来处理接口

    import merchantMng from '@/api/merchantMng'
    import {observable, action, computed} from 'mobx'
    import {dateFormat} from '@/utils/date'
    
    export default class MerchantMng {
        @observable totalRows = 0
        @observable merchantList = []
    
        // 商户管理--查询
        @action queryMerchant = async (params) => {
            const data = await merchantMng.queryMerchant(params)
            try {
                this.merchantList = data.data.record
                this.totalRows = data.data.totalRows
            } catch (e) {
                console.log(e)
            }
        }
    
        @computed get merchantData() {
            try {
                return this.merchantList.map((item, index) => {
                    return {
                        ...item,
                        createTime: dateFormat(item.createTime, 'yyyy-MM-dd HH:mm:ss')
                    }
                })
            } catch (e) {
                return []
            }
        }
    
        // 商户管理--新增
        @action addMerchant = async (params) => {
            return await merchantMng.addMerchant(params)
        }
    }
    

    新建一个index.js

    import MerchantMng from './merchantMng'
    
    class Community {
        constructor() {
            this.MerchantMng = new MerchantMng()
        }
    }
    
    export default Community
    

    ⑵ 在store目录下新建index.js

    import Community from './community'
    
    class RootStore {
        constructor() {
            this.Community = new Community()
        }
    }
    
    const rootStore = new RootStore()
    
    export default rootStore
    

    ⑶ 把store注入全局

    // src/index.jsx文件
    import { Provider } from 'mobx-react'
    import rootStore from './store'
    function render() {
        ReactDOM.render(
            <Provider {...rootStore}>
                <App />
            </Provider>,
            document.getElementById('root'))
    }
    render()
    
    if (module.hot) {
        module.hot.accept(() => {
            render()
        })
    }
    

    ⑷ 在页面中调用接口

    import React, { Component } from 'react'
    import { observer, inject } from 'mobx-react'
    
    @inject('Community') // 给组件注入其需要的 store(利用 React context 机制)
    @observer // 监听store的变化, 同时更新视图的变化
    class MerchantManage extends Component {
        /**
         * 查询商户
         * @param {Number} pageIndex 当前页码
         * @param {Object} carParkMerchant 参数对象
         */
        queryMerchant = (pageIndex = 1, carParkMerchant = {}) => {
            const { MerchantMng } = this.props.Community
            const params = {
                // post和get请求都把参数写在param里
                param: {
                    data: {
                        carParkMerchant,
                        pager: {
                            pageRows: 10,
                            pageIndex,
                            paged: true
                        },
                        orderBy: {
                            orderColumn: 't.createTime',
                            orderType: 'desc'
                        }
                    }
                }
                // headers: { 'content-type': 'application/json' } 请求头需要传参写在这里
            }
            MerchantMng.queryMerchant(params).then(() => {
                this.setState({
                    tbodyData: MerchantMng.merchantData,
                    totalRows: MerchantMng.totalRows,
                    currentPage: pageIndex
                })
            })
        }
    }
    
    9、配置rem

    ⑴ 在public/index.html添加以下代码

    <script>
        function remFont() { 
            var html = document.getElementsByTagName("html")[0];
            var width = document.documentElement.clientWidth;
            var font_Size = 0;
            if(width >= 1366){
                font_Size = 100/1920 * width;
            }else{
                font_Size = 100/1920 * 1366;
            }
            html.style.fontSize = font_Size + "px";
        }
        remFont()
        window.addEventListener('resize', function () {
          remFont()
        })
    </script>
    

    ⑵ 在App.scss中设置html字体大小

    html {
      font-size: 100px;
    }
    
    10、配置px2rem

    ⑴ 安装

    npm install postcss-px2rem-exclude --save
    

    ⑵ 在webpack.config.dev.js和webpack.config.prod.js的"getStyleLoaders"方法中添加以下代码

    {
      // Options for PostCSS as we reference these options twice
      // Adds vendor prefixing based on your specified browser support in
      // package.json
      loader: require.resolve('postcss-loader'),
      options: {
        // Necessary for external CSS imports to work
        // https://github.com/facebook/create-react-app/issues/2677
        ident: 'postcss',
        plugins: () => [
          require('postcss-flexbugs-fixes'),
          require('postcss-preset-env')({
            autoprefixer: {
              flexbox: 'no-2009',
            },
            stage: 3,
          }),
          // 配置px2rem
          require('postcss-px2rem-exclude')({
            remUnit: 100,
            exclude: /node_modules/i,
          })
        ],
        sourceMap: shouldUseSourceMap,
      },
    },
    
    11、引入阿里iconfont

    ⑴ 在src文件夹下新建一个assets文件夹,再新建一个iconfont文件夹,把阿里图库生成的文件放到文件夹下
    ⑵ 在App.jsx中引入

    import './assets/iconfont/iconfont.css'
    
    12、引入antd,配置按需加载

    ⑴ 安装

    npm install antd --save
    npm i babel-plugin-import --save
    

    ⑵ 在webpack.config.dev.js和webpack.config.prod.js中找到"oneOf",在"customize"下方的"plugins"中添加以下代码

    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
    }]
    

    ⑶ 使用组件

    import { Layout } from 'antd'
    
    13、去除build生成的.map文件

    打开文件webpack.config.prod.js,搜索"shouldUseSourceMap",找到第一个结果,注释掉这一行,另起一行把它的值改为false

    // const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
    const shouldUseSourceMap = false;
    
    14、打包后首页空白
    // package.json中添加
    "homepage": "."
    
    15、浏览器es6兼容

    ⑴ 安装babel-polyfill

    npm install --save-dev babel-polyfill
    

    ⑵ 在src/index.js引用

    import 'babel-polyfill'
    
    16、其他目录结构

    ⑴ 在src目录下新建一个pages目录,用来存放开发的页面
    ⑵ 在src目录下新建一个components目录,用来存放封装的组件
    ⑶ 在src目录下新建一个static目录,用来存放本地媒体资源文件
    ⑷ 在src目录下新建一个utils目录,用来存放封装的公共方法,项目中常用的公共方法可参考笔者文章《封装项目中常用的工具函数

    相关文章

      网友评论

          本文标题:create-react-app搭建一个完整的项目

          本文链接:https://www.haomeiwen.com/subject/cgcgpctx.html