实现需求
- 登录页面展示
- 实现注册和登录功能
- 实现登出功能
- 登录成功实现页面跳转
- 短时间不需要再登录
实现过程
创建React项目
注意:新版React和之前有较大不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from 'react'; import { createRoot } from 'react-dom/client'; import App from './App';
const root = createRoot(document.getElementById('root')); root.render( <App></App> );
|
前端UI登录界面基本布局
这部分我是在pages/login/index.js完成的
当然不要忘记把组件放到App中去~
需求:
完成登录界面基本布局
完成登录表单
实现登录界面
采用antd里面的基本布局(header content footer)和表单实现
【不要怕!按照你想的魔改就好了!】
实现效果:
完善注册页面
还是采用antd里面的表单进行实现,这里要注意的是,是点击register now!之后,才会切换到注册页面,这里我觉得注册页面单独没什么必要,所以我采取的是把注册页面嵌套在对话框里面,根据自己的喜好啦~
实现效果:
接口配置
Promise对axios进行二次封装
二次封装的好处在于:
- 实现全局axios模块,因为平时发送网络请求多样,有get请求,post请求等等
- 可以全局部署请求拦截器和响应拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import axios from 'axios'; import qs from 'qs'; import {message} from 'antd';
const instance = axios.create({ timeout: 10000, })
instance.interceptors.request.use(config => { config.headers.Authorization = sessionStorage.getItem('token') || ''; return config; }, err => { return Promise.reject(err); });
instance.interceptors.response.use(response => { console.log(response); if (response.data.msg === '权限校验成功!') { window.history.pushState(null, 'home','/'); } else { return Promise.reject(response.data.msg); } }, err => { if (err.response) { window.history.pushState(null, 'login','/login'); } })
export default function ajax(method='GET', url, data={}, config) {
return new Promise((resolve, reject) => { let promise; if (method === 'GET') { promise = instance({ method:'GET', url, params:data, ...config, }) } else { promise = axios({ method: 'POST', url, data: qs.stringify(data), headers: { 'Context-type': 'application/json', 'Authorization': 'Bearer ' + window.sessionStorage.getItem('token'), }, ...config, }) };
promise.then(response => { resolve(response); }).catch(error => { reject(message.error(error)); }) }) }
|
写接口
接口主要根据写的后端接口配
解决跨域问题
一开始,我采用CORS解决跨域
这说明设置的Origin字段是无效的,不管我设置什么或者不设置这个字段时查看Origin字段时它的值都是null,有人说那个Origin字段本来就应该是浏览器来设置的,自己设置不安全
所以导致我在服务端写了Access-Control-Allow-Origin一直还是没用,所以后面采用了代理的方式进行跨域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) { app.use( "/api", createProxyMiddleware({ target: "http://localhost:5000", changeOrigin: true, pathRewrite: { "^/api": "" }, }) ) }
|
最终接口代码:
1 2 3 4 5 6 7 8 9 10 11
| import ajax from './ajax';
export const reqRegister = (username, password) => ajax('POST', '/api/register', {username, password});
export const reqLogin = (username, password) => ajax('POST', '/api/login', {username, password});
export const reqAuth = () => ajax('POST', '/api/auth', {});
|
路由部署
实现效果:
- 访问home页面,如果没有登录,重定向到login页面
- 登录成功后跳转到home页面
- home页面设置登出
- 设置注册页面,可以提交表单信息
好久没写router了,此时最新的是"react-router-dom": "^6.3.0"
,发现更新了不少~
不要因为不熟悉就卸载下载旧版本呀【以前的我经常这么干!哈哈哈哈哈】
还是要不断学习!拥抱变化!
(干货) 全网最全 react-router-dom v6.0学习指南
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import Home from '../pages/home'; import Login from '../pages/login';
export const routes = [ { path: '/', component: Home, exact: true, }, { path: '/login', component: Login, } ];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import React from 'react'; import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { routes } from './router';
export default function App() { return ( <BrowserRouter> <Routes> { routes.map((route) => ( <Route key={route.path} path={route.path} //exact={route.exact} element={<route.component/>} ></Route> )) } <Route path='*' element={<Navigate to='/login'/>}></Route> </Routes> </BrowserRouter> ) }
|
这样能够实现路由正常跳转了~
接口调用
接口主要用于实现登录功能,所以基本是下面的流程:
- 输入用户名和密码,登录(发送登录请求)
- 根据后端返回的结果判断是哪种状态
- 登录成功:跳转到主页(’/‘),把返回的token存在sessionStorage里面
- 用户不存在:停留在原页面,提示用户不存在
- 用户点击register now!之后,弹出注册页面,用户输入信息后,注册(发送注册请求)
- 密码错误:停留在原页面,提示密码错误,用户需要再次输入
具体看/src/login部分源码吧~
值得注意的是:跳转页面采用useNavigate
自动校验token
我这里采取的是,在login页面渲染的时候发送自动校验的请求,目前只想到这个~
登出页面
我主要设置在home组件里面,登出就很简单,要做的就是:
- 删除sessionStorage里面的token
- 跳转到登录页面(非必要!)
优化思考
优化1: 考虑设置token的有效时长
优化2: 考虑组件间传值
比如用户登陆后可以在home组件访问到是谁登录的,欢迎XXX
诸如此类
知识点总结
- 登录流程
antd
组件应用
axios
请求相关:封装、请求头设置、发请求、拦截器等
- 跨域
- react-router:基本配置,跳转路由
- token相关
- cookie sessionStorage localStorage
参考
antd
styled-components
(干货) 全网最全 react-router-dom v6.0学习指南