用到的技术栈:
前端:React+create-react-app+redux+react-router+Antd
后台:Koajs+Mysql8.0+sequalize(ORM模型)+redis(数据缓存)
项目放于我的gitee,随缘更新,前端传送门:Excharhttps://gitee.com/exchar/homepage.githttps://gitee.com/exchar/homepage.git
后端传送门:
第一人称写代码?
一、安装create-react-app脚手架,创建前端项目
首先安装Nodejs,安装完成后记得替换npm源:
查看npm相关配置:
npm config get registry
设置为淘宝源:
npm config set registry https://registry.npm.taobao.org/
安装create-react-app:
npm install create-react-app -g
创建react项目:
create-react-app my-home-page 注意:项目名不能用驼峰,可以使用连接符'-'
二、目录结构
注:index.js为项目入口文件,App.js为提供的示例文件,开发时需要改造App.js,放置路由
三、基础准备,安装依赖、配置
1.安装sass预处理,需要安装node-sass
2.安装Antd组件库,
npm install antd -S
3.安装antd图标库,
npm install --save @ant-design/icons
4.释放配置文件,
npm run eject
,提示是否继续,输入y,回车
四、改造入口文件
删除App.js中的示例代码,删除后的样子:
import './App.css';
function App() {
return (
<div className="App">
</div>
);
}
export default App;
在src下新建router文件夹,安装react-router,
npm install react-router-dom -s -d 或者 yarn add react-router-dom -s -d
在src下新建utils文件夹,为了让路由加载体验更佳,安装nprogress进度条,
npm install nprogress -s
新建ProgressRoute组件,将基础路由Route组件用nprogress组件包起来,ProgressRoute组件:
import React from 'react'
import { Route } from 'react-router-dom'
import nprogress from 'nprogress'
import 'nprogress/nprogress.css';
const ProgressRoute = props => {
React.useState(nprogress.start());
React.useEffect(() => {
nprogress.done();
return () => nprogress.start();
});
return (
<Route {...props} />
);
};
export default ProgressRoute
接下来编写路由验证文件 router.js:
import React, { Suspense, lazy } from "react";
import { Redirect, Switch } from "react-router-dom";
import { Spin } from "antd";
import Layout from "../Layout/Index";
import ProgressRoute from "../utils/ProgressRoute";
// exact属性为true时路径中的hash值必须和path完全一致才渲染对应的组件,如果为false则'/'也可以匹配'/login';
// (如果strict属性为false,则末尾是否包含反斜杠结尾不影响匹配结果)
// strict属性主要就是匹配反斜杠,规定是否匹配末尾包含反斜杠的路径,如果strict为true,则如果path中不包含反斜杠结尾,
// 则他也不能匹配包含反斜杠结尾的路径,这个需要和exact结合使用
const permissions = "user"; //登录接口获取的当前用户的角色
const requiresAuth = true; //是否已经登录
//所有的路由
export const routes = [
{
path: "/",
exact: true,
requiresAuth: false,
permissions: ["user", "admin"],
showInMenu:false,
render: () => <Redirect to="/home" />,
},
{
path: "/home",
name: "Home",
exact: true,
strict: true,
showInMenu:true,
requiresAuth: false, //是否需要登录
permissions: ["user", "admin"], // 当前登录权限必须 user或admin 才可以访问
component: lazy(() => import("../pages/Home.js")), //路由懒加载
meta: { title: "我的主页", icon: "DatabaseTwoTone" },
},
{
path: "/login",
name: "Login",
exact: true,
strict: true,
requiresAuth: false, //是否需要登录
permissions: ["user", "admin"], // 当前登录权限必须 user或admin 才可以访问
component: lazy(() => import("../pages/Login.js")), //路由懒加载
meta: { title: "登录呢", icon: "login" },
},
];
export const renderRoutes = (routes, extraProps = {}, switchProps = {}) => {
return routes ? (
<Suspense
fallback={
<div
style={{
width: "100vw",
height: "100vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<Spin tip="加载中"></Spin>
</div>
}
>
<Switch {...switchProps}>
{routes.map((item, i) => (
<ProgressRoute
key={item.name || i}
path={item.path}
exact={item.exact}
strict={item.strict}
render={(props) => routeRender(item, props, extraProps)}
/>
))}
</Switch>
</Suspense>
) : null;
};
const routeRender = (route, props, extraProps) => {
// 登录判断(需要登录 && 未登录-->跳登录页面,,,,,,,不需要登录 || 已经登录-->正常跳转)
const login = route.requiresAuth && !requiresAuth; //跳登录
// 该角色是否有权限访问该页面(当前角色是否在 路由要求角色数组中)
const auth = route.permissions.includes(permissions); //有权限
if (login) {
return <Redirect to={{ path: "/login", message: "请登录后再操作!" }} />;
} else {
if (auth) {
return route.render ? (
route.render({ ...props, ...extraProps, route: route.routes })
) : (
<route.component {...props} {...extraProps} route={route} />
);
} else {
alert("您暂无权限");
return <Redirect to={{ path: "/login", message: "请登录后再操作!" }} />;
}
}
};
export const basicRoutes = [
{
path: "/index",
name: "Index",
exact: true,
strict: true,
requiresAuth: false, //是否需要登录
permissions: ["user", "admin"], // 当前登录权限必须 user或admin 才可以访问
component: ()=>Layout,
meta: { title: "登录呢", icon: "login" },
},
{
path: "/",
exact: true,
requiresAuth: false,
permissions: ["user", "admin"],
render: () => <Redirect to="/index" />,
},
]
对于Route的使用,由于需要悬浮头像和导航,需要嵌套的路由控制
附主页布局:
在App.js中使用路由并构建主页布局组件:
import "./App.css";
import Layout from "./Layout/Index";
import { basicRoutes, renderRoutes } from "./router/router";
import { HashRouter, Switch } from "react-router-dom";
function App() {
return (
<div className="App">
<HashRouter>
<Switch>
<Layout>{renderRoutes(basicRoutes)}</Layout>
</Switch>
</HashRouter>
</div>
);
}
export default App;
在src目录下创建布局文件,路径/src/Layout/Index.js
import React, { Component } from "react";
import { renderRoutes, routes } from "../router/router";
import { Switch } from "react-router-dom";
export default class Layout extends Component {
render() {
return (
<div>
<div>悬浮区域</div>
<Switch>{renderRoutes(routes)}</Switch>
</div>
);
}
}
在src目录下新建pages文件夹,用来存放页面,新建空白页面Home.js,Login.js;
完成后
目录结构:
这里推荐一个vscode插件
直接在编辑器里面输入rcc即可快速创建一个空白的React class组件。
相关资料:
React官方文档:
遇到的一些问题:
1.node-sass安装报错,安装python2.7和visual studio build tools,安装时选择适用于C++的桌面开发,安装完成后设置版本:npm config set msvs_version 2019
{[(-_-)(-_-)]},over。