create-react-app 项目搭建

本文介绍了如何在React项目中创建项目、配置src别名,引入并使用react-router-dom进行路由管理,整合less和SASS样式,以及集成Redux状态管理、国际化和AntdPro组件库的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、创建项目

npx create-react-app  my-app
cd my-app
yarn start

配置src别名

运行命令 ,暴露 config

yarn eject

进入 webpack.config.js中,找到 alias 添加以下2行

// 文件路径别名
'@': path.resolve(__dirname, '../src'),
'@pages': path.resolve(__dirname, '../src/pages'),

2、引入路由(使用5版本)

yarn add react-router-dom@5
  1. 编写 AppRouter,包裹所有路由配置Route
import { HashRouter, BrowserRouter, Switch, Route, Redirect } from 'react-router-dom'
import routerMapping from './router-mapping';

function AppRouter(porps) {

    // 权限过滤
    const handleFilter = route =>{
        // true 有权限,false 无权限
        return true;
    }

    return (
        <HashRouter>
            <Switch>
                <Redirect exact from="/" to="/home" />
                {routerMapping.map((route) => {
                    return (
                    handleFilter(route) && (
                        <Route
                        component={route.component}
                        key={route.path}
                        path={route.path}
                        />
                    )
                    );
                })}
                <Redirect to="/error/404" />
            </Switch>
        </HashRouter>
    )
}

export default AppRouter;
  1. 编写 router-mapping.js
import Loadable from 'react-loadable';
import Loading from '@/components/Loading'

const Home = Loadable({loader: () => import(/*webpackChunkName:'Home'*/'@/pages/home'),loading: Loading});
const Error404 = Loadable({loader: () => import(/*webpackChunkName:'Home'*/'@/pages/error/404'),loading: Loading});

export default [
  { path: "/home", component: Home, roles: ["admin","editor","guest"] },
  { path: "/error/404", component: Error404, roles: ["admin","editor","guest"] },
]
  1. 编写菜单 router-menu-config.js
export const RouterMenuConfig = [
    {
        title: "首页",
        path: "/home",
        icon: "home",
        roles:["admin","editor","guest"]
    },
];

3、引入less

1、安装

yarn add less less-loader -S

2、webpack.config.js中
定义:

const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;

rule中

{
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction
                    ? shouldUseSourceMap
                    : isEnvDevelopment,
                  modules: {
                    mode: 'icss',
                  },
                },
                'less-loader'
              ),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true,
            },
            {
              test: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction
                    ? shouldUseSourceMap
                    : isEnvDevelopment,
                  modules: {
                    mode: 'local',
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                'less-loader'
              ),
            },

3、重启项目
4、界面中应该就生效了

.home-container {
    background-color: red;
    .title {
        color: #fff;
    }
}
import react from 'react'
import './home.less'

export default function() {

    return (
        <div className="home-container">
            <div className='title'>标题</div>
            this is home page.
        </div>
    )
}

4、引入 sass

1、项目中应该有默认引入依赖了,package.json中

   "sass-loader": "^12.3.0",

2、安装 node-sass
这里安装了:

“node-sass”: “^9.0.0”,

yarn add node-sass

5、引入 redux相关

yarn add redux react-redux redux-thunk

默认最新的安装的版本如下:

"react-redux": "^9.0.4",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
  • 1、创建全局 store
import { createStore, applyMiddleware } from 'redux'
import reduxThunk from 'redux-thunk'
import reducer from './reducers'

const store = createStore(reducer, applyMiddleware(reduxThunk));

export default store
  • 2、创建 reducers
// app.js
import { ActionTypes } from "../action-types";

const initState = {
    lang: 'zh',
}

export default function app(state = initState, action) {
    switch(action.type) {
        case ActionTypes.App.UPDATE_LANGE: {
            return {
                ...state,
                lang: action.lang
            }
        }
        default: 
            return state;
    }
}
// index.js

import { combineReducers } from "redux";

import app from './app'

export default combineReducers({
    app
})
  • 3、创建 actions
// app.js
import { ActionTypes } from "../action-types"
export const app_update_lang = lang =>{
    return {
        type: ActionTypes.App.UPDATE_LANGE,
        lang: lang
    }
}
  • 4、创建 actions常量定义,文件夹:action-types
// action-types

export const ActionTypes = {
    App: {
        // 更新语言
        UPDATE_LANGE: 'updateLange'
    }
}

  • 5、创建 controller (自定义的一个便捷控制层)
// StoreController // 用于 全局的 
import { AppStoreController } from "./app-store-controller";

export class StoreController {

    static dispatch = null;

    static RegisterDispatch(dispatch) {
       this._saveDispatch(dispatch)
    }

    static _saveDispatch(dispatch) {
        if(dispatch) {
            this.dispatch = dispatch;
            AppStoreController.dispatch = dispatch;
        }
    }
}
// app-store-controller.js

import { app_update_lang } from "../actions/app";
export class AppStoreController {

    static dispatch;

    /**
     * 更新语言
     * @param {*} lang 
     */
    static UpdateLang(lang) {
        this.dispatch(
            app_update_lang(lang)
        )
    } 

    /**
     * 更新语言到 en
     */
    static UpdateLang_EN() {
        this.UpdateLang("en")
    }

    /**
     * 更新语言到 zh
     */
    static UpdateLang_ZH() {
        this.UpdateLang("zh")
    }
}
  • 5、连接状态
// App.js 入口文件中
import logo from './logo.svg';
import './App.css';
import MyRoute from './router'
import { Provider } from "react-redux";
import store from "./store";

function App() {
  return (
    // redux
    <Provider store={store}>
      <MyRoute />
    </Provider>
  )
}

export default App;

  • 6、全局dispatch存储

可以在最顶层的 conncet文件中,获取到dispatch来存储
这里展示是 MyRoute中,因为这个是路由的入口文件,所以这个就是顶层的项目入口

// src\router\index.js
import { HashRouter, BrowserRouter, Switch, Route, Redirect } from 'react-router-dom'
import routerMapping from './router-mapping';
import { connect } from "react-redux";
import { useEffect, useState } from 'react';
import { StoreController } from '../store/controller';

function AppRouter(props) {

    // 权限过滤
    const handleFilter = route =>{
        // true 有权限,false 无权限
        return true;
    }

    useEffect(()=>{
        if(props.dispatch) {
            StoreController.RegisterDispatch(props.dispatch); // 保存 dispatch
            console.log("保存 dispatch", props.dispatch); 
        }
    }, [props.dispatch])

    return (
        <HashRouter>
            <Switch>
                <Redirect exact from="/" to="/home" />
                {routerMapping.map((route) => {
                    return (
                    handleFilter(route) && (
                        <Route
                            component={route.component}
                            key={route.path}
                            path={route.path}
                        />
                    )
                    );
                })}
                <Redirect to="/error/404" />
            </Switch>
        </HashRouter>
    )
}

export default connect((state) =>{
    return {
        lang: state.app.lang
    }
},dispatch =>{
    return {
        dispatch: dispatch, // 这里 dispatch 暴露进界面
    }
})(AppRouter);

6、引入国际化库

Format.JS
文档:https://formatjs.io/docs/getting-started/installation

  • 安装
 yarn add react-intl
  • 默认安装的版本:
    "react-intl": "^6.5.5",
  • 创建 i18n文件
import { FormattedMessage } from 'react-intl'

/*

id 对应的就是zh-CN.js中的配置的键值, 该组件的值就是键值对应的value	
values 是 {},里面可以定义变量,示例如下
    {name: '张三'}
    - 如果文字里面是这样的: 我叫{name} 
    - 解析出来就是:我叫张三
defaultMessage id对应的key不存在时,这个是默认的值
*/

// 存储 i18n暴露的函数api intl

let I18nIntl = null;

export function setI18nIntl(val) {
    // console.log("设置 i18n api: ", val);
    I18nIntl = val;
}

/**
 * react dom形式获取国际化
 * @param {*} param0 
 * @returns 
 */
export const I18nMessageDom = function({
    id, values = {}, defaultMessage = ""
}) {
    return (
        <FormattedMessage
            id={id} 
            values={values} // values 是 {},里面可以定义变量,示例如下
            defaultMessage={defaultMessage}
        />
    )
}

/**
 * api形式获取国际化
 * @param {*} param0 
 * @returns 
 */
export const getI18nMessage = function({
    id, values = {}, defaultMessage = ""
}) {
    if(I18nIntl) {
        return I18nIntl.formatMessage({
            id, values, defaultMessage
        });
    }
    return defaultMessage;
}
  • 如果需要使用存储 api形式 intl函数的话,需要在入口文件中,使用高阶组件 injectIntl 包裹暴露出去
    ,在props中获取到intl
export default 
    // 这个是redux的
    connect((state) =>{
        console.log("state -->", state);
        return {
            lang: state.app.lang
        }
    },dispatch =>{
        return {
            dispatch: dispatch,
        }
    })(
        // 这个是 i18n的,用于获取到 api式获取国际化的api函数:intl
        injectIntl(LayoutMain)
    );

7、引入组件库(Antd)

这里使用 antd + pro

yarn add antd  @ant-design/pro-components
  • 使用

import { Button } from 'antd'

return (
     <div>
     		<div>
          antd 示例
          </div>

          <Button type="primary">确定</Button>
          <br/>
          <br/>
          <Button type="dashed">取消</Button>
     </div>
  )

|
|
|
|
END

至此项目搭建基本完成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值