【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现
项目搭建
-
创建项目
# 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js}
- 使用
npx create-react-app
创建项目,进入项目目录后通过npm start
启动。 - 调整项目目录结构,包括
apis
、assets
、components
、pages
等多个文件夹。
- 使用
-
使用技术
- 接入
scss
预处理器,安装sass
工具,创建全局样式文件index.scss
。# 安装sass工具 npm i sass -D
// 在src/index.scss中设置全局样式 body {font-family: Arial, sans-serif;background-color: #f4f4f4; }
- 引入组件库
antd
,安装后在Login
页面测试Button
组件。# 安装antd组件库 npm i antd
// 在src/pages/Login/index.jsx中使用Button组件 import React from 'react'; import { Button } from 'antd';const Login = () => {return (<div><Button type='primary'>登录</Button></div>); };export default Login;
- 使用
react-router-dom
配置基础路由,创建Layout
和Login
组件并配置路由规则。# 安装react-router-dom npm i react-router-dom
// 在src/router/index.js中配置路由 import { createBrowserRouter } from 'react-router-dom'; import Login from '../pages/Login'; import Layout from '../pages/Layout';const router = createBrowserRouter([{path: '/',element: <Layout />,},{path: '/login',element: <Login />,}, ]);export default router;
- 通过
craco
工具包配置别名路径,在craco.config.js
中设置webpack
别名,并在jsconfig.json
中配置VsCode
提示。# 安装craco工具包 npm i @craco/craco -D
// 在craco.config.js中配置别名 const path = require('path'); module.exports = {webpack: {alias: {'@': path.resolve(__dirname,'src')}} };
// 在package.json中修改scripts命令 "scripts": {"start": "craco start","build": "craco build","test": "craco test","eject": "react-scripts eject" }
// 在src/router/index.js中使用别名 import { createBrowserRouter } from 'react-router-dom'; import Login from '@/pages/Login'; import Layout from '@/pages/Layout';const router = createBrowserRouter([{path: '/',element: <Layout />,},{path: '/login',element: <Login />,}, ]);export default router;
// 在jsconfig.json中配置VsCode提示 {"compilerOptions": {"baseUrl": "./","paths": {"@/*": ["src/*"]}} }
- 接入
-
功能模块实现
-
登录模块
-
基本结构搭建
-
-
- 在
Login/index.js
创建登录页面结构,引入antd
组件,使用@/assets
路径引入图片,在Login/index.scss
中设置样式。 -
import React from 'react'; import { Card, Form, Input, Button } from 'antd'; import logo from '@/assets/logo.png'; import './index.scss';const Login = () => {return (<div className="login"><Card className="login-container"><img className="login-logo" src={logo} alt="" /><Form><Form.Item><Input size="large" placeholder="请输入手机号" /></Form.Item><Form.Item><Input size="large" placeholder="请输入验证码" /></Form.Item><Form.Item><Button type="primary" htmlType="submit" size="large" block>登录</Button></Form.Item></Form></Card></div>); };export default Login;
-
表单校验实现
- 为
Form
组件设置validateTrigger
,为Form.Item
组件设置name
和rules
属性进行表单校验。import React from 'react'; import { Form, Input, Button } from 'antd';const Login = () => {return (<Form validateTrigger={['onBlur']}><Form.Itemname="mobile"rules={[{ required: true, message: '请输入手机号' },{pattern: /^1[3-9]\d{9}$/,message: '手机号码格式不对'}]}><Input size="large" placeholder="请输入手机号" /></Form.Item><Form.Itemname="code"rules={[{ required: true, message: '请输入验证码' },]}><Input size="large" placeholder="请输入验证码" maxLength={6} /></Form.Item><Form.Item><Button type="primary" htmlType="submit" size="large" block>登录</Button></Form.Item></Form>); };export default Login;
- 为
-
获取登录表单数据
- 为
Form
组件设置onFinish
属性,在点击登录按钮时触发获取表单数据的函数。import React from 'react'; import { Form, Input, Button } from 'antd';const Login = () => {const onFinish = formValue => {console.log(formValue);};return (<Form onFinish={onFinish}><Form.Item><Input size="large" placeholder="请输入手机号" /></Form.Item><Form.Item><Input size="large" placeholder="请输入验证码" /></Form.Item><Form.Item><Button type="primary" htmlType="submit" size="large" block>登录</Button></Form.Item></Form>); };export default Login;
- 为
-
封装 request 工具模块
- 安装
axios
,在utils/request.js
中创建axios
实例,配置baseURL
、请求拦截器和响应拦截器。# 安装axios npm i axios
import axios from 'axios';const http = axios.create({baseURL: 'http://example.com/api',timeout: 5000 });// 请求拦截器 http.interceptors.request.use(config => {return config; }, error => {return Promise.reject(error); });// 响应拦截器 http.interceptors.response.use(response => {return response.data; }, error => {return Promise.reject(error); });export { http };
- 安装
-
使用 Redux 管理 token
- 安装
react-redux
和@reduxjs/toolkit
,在store
中创建userStore
切片,设置token
初始状态和setUserInfo
等reducers
,封装fetchLogin
异步方法。# 安装react-redux和@reduxjs/toolkit npm i react-redux @reduxjs/toolkit
import { createSlice } from '@reduxjs/toolkit'; import { http } from '@/utils';const userStore = createSlice({name: 'user',initialState: {token: ''},reducers: {setUserInfo(state, action) {state.token = action.payload;}} });const { setUserInfo } = userStore.actions; const userReducer = userStore.reducer;const fetchLogin = loginForm => {return async dispatch => {const res = await http.post('/authorizations', loginForm);dispatch(setUserInfo(res.data.token));}; };export { fetchLogin }; export default userReducer;
- 安装
-
实现登录逻辑
- 在
Login
组件中调用fetchLogin
方法,登录成功后跳转到首页并提示。import React from 'react'; import { message } from 'antd'; import { useDispatch } from 'react-redux'; import { fetchLogin } from '@/store/modules/user';const Login = () => {const dispatch = useDispatch();const onFinish = async formValue => {await dispatch(fetchLogin(formValue));message.success('登录成功');};return (<div><form onSubmit={onFinish}>{/* 登录表单字段 */}</form></div>); };export default Login;
- 在
-
token 持久化
- 封装
setToken
、getToken
和clearToken
方法,在userStore
中setUserInfo
时将token
存入本地。// 在@/utils/token.js中封装存取方法 const TOKENKEY = 'token_key';function setToken(token) {return localStorage.setItem(TOKENKEY, token); }function getToken() {return localStorage.getItem(TOKENKEY); }function clearToken() {return localStorage.removeItem(TOKENKEY); }export {setToken,getToken,clearToken };
// 在userStore中使用token持久化方法 import { createSlice } from '@reduxjs/toolkit'; import { http } from '@/utils'; import { getToken, setToken } from '@/utils/token';const userStore = createSlice({name: 'user',initialState: {token: getToken() || ''},reducers: {setUserInfo(state, action) {state.token = action.payload;setToken(state.token);}} });export default userStore;
- 封装
-
请求拦截器注入 token
- 在
request.js
的请求拦截器中,判断是否有token
,有则添加到请求头Authorization
中。// 在utils/request.js中注入token import axios from 'axios';const http = axios.create({baseURL: 'http://example.com/api',timeout: 5000 });http.interceptors.request.use(config => {const token = getToken();if (token) {config.headers.Authorization = `Bearer ${token}`;}return config; }, error => {return Promise.reject(error); });http.interceptors.response.use(response => {return response.data; }, error => {return Promise.reject(error); });export { http };
- 在
-
路由鉴权实现
- 在
components/AuthRoute/index.jsx
中创建路由鉴权高阶组件,判断本地是否有token
,决定是否重定向到登录页面。import React from 'react'; import { Navigate } from 'react-router-dom'; import { getToken } from '@/utils';const AuthRoute = ({ children }) => {const isToken = getToken();if (isToken) {return <>{children}</>;} else {return <Navigate to="/login" replace />;} };export default AuthRoute;
// 在src/router/index.js中使用AuthRoute组件 import { createBrowserRouter } from 'react-router-dom'; import Login from '@/pages/Login'; import Layout from '@/pages/Layout'; import AuthRoute from '@/components/AuthRoute';const router = createBrowserRouter([{path: '/',element: <AuthRoute><Layout /></AuthRoute>,},{path: '/login',element: <Login />,}, ]);export default router;
- 在
-
Layout 模块
-
基本结构和样式 reset
- 在
pages/Layout/index.js
中使用antd/Layout
组件创建页面结构,引入antd
的Menu
和Popconfirm
等组件,设置样式并安装normalize.css
进行样式 reset。import React from 'react'; import { Layout, Menu, Popconfirm } from 'antd'; import { HomeOutlined, DiffOutlined, EditOutlined, LogoutOutlined } from '@ant-design/icons'; import './index.scss'; import 'normalize.css';const { Header, Sider } = Layout;const items = [{label: '首页',key: '1',icon: <HomeOutlined />,},{label: '文章管理',key: '2',icon: <DiffOutlined />,},{label: '创建文章',key: '3',icon: <EditOutlined />,}, ];const GeekLayout = () => {return (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">用户名</span><span className="user-logout"><Popconfirm title="是否确认退出?" okText="退出" cancelText="取消"><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"defaultSelectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}>内容</Layout></Layout></Layout>); };export default GeekLayout;
- 在
-
二级路由配置
- 在
pages
目录创建Home
、Article
、Publish
页面文件夹,在router/index.js
中配置嵌套子路由,在Layout
中配置二级路由出口,使用Link
修改左侧菜单内容实现路由切换。// 在pages目录创建Home.jsx import React from 'react';const Home = () => {return <div>首页内容</div>; };export default Home;
// 在pages目录创建Article.jsx import React from 'react';const Article = () => {return <div>文章管理内容</div>; };export default Article;
// 在pages目录创建Publish.jsx import React from 'react';const Publish = () => {return <div>发布文章内容</div>; };export default Publish;
// 在src/router/index.js中配置二级路由 import { createBrowserRouter } from 'react-router-dom'; import Login from '@/pages/Login'; import Layout from '@/pages/Layout'; import Publish from '@/pages/Publish'; import Article from '@/pages/Article'; import Home from '@/pages/Home'; import { AuthRoute } from '@/components/AuthRoute';const router = createBrowserRouter([{path: '/',element: (<AuthRoute><Layout /></AuthRoute>),children: [{index: true,element: <Home />,},{path: 'article',element: <Article />,},{path: 'publish',element: <Publish />,},],},{path: '/login',element: <Login />,}, ]);export default router;
// 在Layout组件中配置二级路由出口 import React from 'react'; import { Outlet } from 'react-router-dom';const GeekLayout = () => {return (<Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout>); };export default GeekLayout;
- 在
-
路由菜单点击交互实现
- 为
Menu
组件设置onClick
属性实现点击菜单跳转路由,通过useLocation
获取当前路由路径实现菜单反向高亮。import React from 'react'; import { Outlet, useNavigate } from 'react-router-dom'; import { HomeOutlined, DiffOutlined, EditOutlined, LogoutOutlined } from '@ant-design/icons';const items = [{label: '首页',key: '/',icon: <HomeOutlined />,},{label: '文章管理',key: '/article',icon: <DiffOutlined />,},{label: '创建文章',key: '/publish',icon: <EditOutlined />,}, ];const GeekLayout = () => {const navigate = useNavigate();const menuClick = route => {navigate(route.key);};return (<Layout><Header className="main-header"><div className="logo" /><div className="user-info"><span className="user-name">用户名</span><span className="user-logout"><Popconfirm title="是否确认退出?" okText="退出" cancelText="取消"><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"selectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}onClick={menuClick}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout></Layout>); };export default GeekLayout;
// 菜单反向高亮实现 import React from 'react'; import { Outlet, useLocation } from 'react-router-dom'; import { HomeOutlined, DiffOutlined, EditOutlined, LogoutOutlined } from '@ant-design/icons';const items = [{label: '首页',key: '/',icon: <HomeOutlined />,},{label: '文章管理',key: '/article',icon: <DiffOutlined />,},{label: '创建文章',key: '/publish',icon: <EditOutlined />,}, ];const GeekLayout = () => {const location = useLocation();const selectedKey = location.pathname;return (<Layout><Header className="main-header"><div className
- 为
-
展示个人信息
- 在
store/userStore.js
中编写获取用户信息的逻辑,在Layout
组件中触发fetchUserInfo
方法获取信息并渲染用户名。// store/userStore.js import { createSlice } from '@reduxjs/toolkit'; import { http } from '@/utils'; import { getToken, setToken } from '@/utils';const userStore = createSlice({name: 'user',initialState: {token: getToken() || '',userInfo: {}},reducers: {setUserToken(state, action) {state.token = action.payload;setToken(state.token);},setUserInfo(state, action) {state.userInfo = action.payload;},clearUserInfo(state) {state.token = '';state.userInfo = {};clearToken();}} });// 解构出actionCreater const { setUserToken, setUserInfo, clearUserInfo } = userStore.actions; // 获取reducer函数 const userReducer = userStore.reducer;const fetchLogin = (loginForm) => {return async (dispatch) => {const res = await http.post('/authorizations', loginForm);dispatch(setUserToken(res.data.token));}; };const fetchUserInfo = () => {return async (dispatch) => {const res = await http.get('/user/profile');dispatch(setUserInfo(res.data));}; };export { fetchLogin, fetchUserInfo, clearUserInfo }; export default userReducer;
- 在
-
退出登录实现
- 为
Popconfirm
添加确认回调事件,在store/userStore.js
中新增clearUserInfo
方法删除token
和用户信息,在回调事件中调用该方法并返回登录页面。// pages/Layout/index.js import React, { useEffect } from 'react'; import { Layout, Menu, Popconfirm } from 'antd'; import {HomeOutlined,DiffOutlined,EditOutlined,LogoutOutlined, } from '@ant-design/icons'; import { useDispatch, useSelector } from 'react-redux'; import { fetchUserInfo } from '@/store/modules/user';const { Header, Sider } = Layout;const items = [// 菜单配置项 ];const GeekLayout = () => {const dispatch = useDispatch();const name = useSelector(state => state.user.userInfo.name);useEffect(() => {dispatch(fetchUserInfo());}, [dispatch]);const loginOut = () => {dispatch(clearUserInfo());// 假设这里有合适的导航函数,替换为实际的导航逻辑// navigate('/login'); };return (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">{name}</span><span className="user-logout"><Popconfirmtitle="是否确认退出?"okText="退出"cancelText="取消"onConfirm={loginOut}><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"defaultSelectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}>{/* 页面内容 */}</Layout></Layout></Layout>); };export default GeekLayout;
- 为
-
处理 Token 失效
- 在
http.interceptors.response
中判断响应状态码为401
时,清除token
,跳转到登录页面并刷新页面。// 在http.js(假设是配置axios请求相关的文件)中处理Token失效 import axios from 'axios';const http = axios.create({baseURL: 'http://example.com/api',timeout: 5000 });http.interceptors.response.use((response) => {return response.data; }, (error) => {if (error.response && error.response.status === 401) {// 假设这里有合适的获取和清除token的函数,替换为实际的逻辑const token = getToken();if (token) {clearToken();}// 假设这里有合适的导航函数,替换为实际的导航逻辑// navigate('/login'); window.location.reload();}return Promise.reject(error); });export { http };
- 在
-
相关文章:

【React】入门Day04 —— 项目搭建及登录与表单校验、token 管理、路由鉴权实现
项目搭建 创建项目 # 使用npx创建项目 npx create-react-app my-react-app # 进入项目目录 cd my-react-app # 创建项目目录结构 mkdir -p src/{apis,assets,components,pages,store,utils} touch src/{App.js,index.css,index.js} 使用npx create-react-app创建项目࿰…...

CMake 属性之目录属性
【写在前面】 CMake 的目录属性是指在特定目录(及其子目录)范围内有效的设置。 这些属性不同于全局变量或目标(Target)属性,它们提供了一种机制,允许开发者为项目中的不同部分定义不同的构建行为。 通过目录…...

ChatGPT:引领人工智能新潮流!
一、ChatGPT 是什么? 1. ChatGPT 的强大功能和广泛应用。 ChatGPT 作为一款先进的 AI 语言模型,拥有众多强大功能。它可以进行文本生成、文本分类、情感分析、机器翻译等多种自然语言处理任务。同时,ChatGPT 还能进行对话式交互,…...

【银河麒麟高级服务器操作系统】安全配置基线相关分析全过程及解决方案
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 服务器环境以及配置 【机型】物理机或虚机 【…...

用Python实现图片转ASCII艺术:图像处理与字符艺术的完美结合
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 ASCII艺术是一种通过字符来表现图像的艺术形式,最早用于早期计算机显示器,它仅支持字符显示。如今,尽管图像分辨率和显示技术得到了极大的提升,ASCII艺术作为一种复古而别具一格的图像表现形式,仍然受到许多…...

大数据-162 Apache Kylin 全量增量Cube的构建 Segment 超详细记录 多图
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

Redis-缓存过期淘汰策略
缓存淘汰策略 生产上redis内存设置为多少 设置为最大内存的 3/4 redis 会占用物理机多少内存 默认大小是 0,64 位系统下表示不限制内存大小,32位系统表示 3G 如何设置修改redis内存大小 config get maxmemory 查看修改方式 配置文件 单位是字节 2.…...

如何设置LED电子显示屏的屏幕参数?
LED电子显示屏因其高亮度、低能耗和长寿命等优点,在广告、信息显示等领域得到了广泛应用。正确设置屏幕参数对于确保显示屏的最佳性能至关重要。以下是LED电子显示屏设置屏幕参数的步骤: 1. 确定屏幕参数 在开始设置之前,需要了解显示屏的基本…...

Spring Boot Starter Parent介绍
引言 spring-boot-starter-parent 是一个特殊的项目,为基于 Spring Boot 的应用程序提供默认配置和默认依赖。 在本 Spring Boot 教程中,我们将深入了解所有 Spring Boot 项目内部使用的 spring-boot-starter-parent 依赖项。我们将探讨此依赖项所提供…...

【含开题报告+文档+PPT+源码】基于SpringBoot乡村助农益农平台的设计与实现
开题报告 近年来,随着社会经济的快速发展和人民生活水平的提高,人们对优质农产品的需求越来越高。然而,传统的农产品销售管理模式存在一些问题。首先,农产品供应链信息不透明,导致生产者难以了解市场需求和价格变动趋…...

数据中心运维挑战:性能监控的困境与智能化解决方案的探寻
随着数字化进程的加速,数据中心已成为企业信息架构的核心支撑,其运维管理的复杂度和重要性也随之提升。运维团队需应对设备老化、资源分配失衡、性能波动等多重难题,以确保数据中心持续高效运行。 其中,性能监控作为运维管理的关键…...

基于SSM的民宿管理系统【附源码】
基于SSM的民宿管理系统(源码L文说明文档) 目录 4 系统设计 4.1 系统概要设计 4.2 系统功能结构设计 4.3 数据库设计 4.3.1 数据库E-R图设计 4.3.2 数据库表结构设计 5 系统实现 5.1用户信息管理 5.2 房东信息管理…...

显卡 3090 vs v100
1.3090 Date: 2020 AmperePielines/ Cuda cores: 10496 2.V100 Date: 2018 VoltaPielines/ Cuda cores: 5129 3.结构 & Core比较: v100优点: v100功耗小v100较快的双精度(fp64)和混合精度(fp16fp32)pcie版的NVLink与2080ti完全一致 v100缺点: 不支持整数格式计算&…...

怎么在单片机裸机程序中移植EasyLogger?
1、介绍 EasyLogger 是一款超轻量级、高性能的C日志库,非常适合对资源敏感的软件项目。例如:IoT产品、可穿戴设备、智能家居等等。相比log4c、zlog这些知名的C日志库,EasyLogger的功能更加简单,提供给用户的接口更少,但…...

C/C++解析文件名和目录路径
文章目录 主要函数使用注意事项示例程序总结 #include <libgen.h> 是一个 C/C 语言的头文件,主要用于字符串处理,特别是在处理文件路径时。它提供了一些函数来帮助你解析文件名和目录路径。 主要函数 以下是 libgen.h 中一些常见的函数ÿ…...

Git 基本命令行操作
Git是一个开源的分布式版本控制系统,用于管理源代码和文档的版本。以下是Git的基本命令行操作: 一、配置 安装完成后,需要配置Git的用户名和邮箱,以便在提交记录时记录操作者的信息。 配置全局用户名:git config --g…...

【Rust练习】17.泛型
练习题来自:https://practice-zh.course.rs/generics-traits/generics.html 函数 1 // 填空 struct A; // 具体的类型 A. struct S(A); // 具体的类型 S. struct SGen<T>(T); // 泛型 SGen.fn reg_fn(_s: S) {}fn gen_spec_t(_s: SGen<A&…...

java脚手架系列4--测试用例、拦截器
异常处理、拦截器、数据库连接 1 测试用例 单元测试是一个老生常谈的问题,无论是后端对自己的代码质量把的第一道关也好,也是对测试减缓压力。这里就不过多讲述测试用例的重要性,但是有2个框架我们必须了解一下。 1.1 JUnit和mockito 我们…...

论文推荐 |【Agent】自动化Agent设计系统
论文标题: Automated Design of Agentic Systems 论文地址: https://arxiv.org/abs/2408.08435 GitHub地址: https://github.com/ShengranHu/ADAS 自动化代理设计在性能和通用性方面显著超越了手动方法。 • 引入了自动化代理系统设计&am…...

Linux操作系统提供了五种主要的IO(输入/输出)模型
Linux操作系统提供了五种主要的IO(输入/输出)模型,这些模型旨在优化应用程序对输入输出操作的管理和处理。以下是关于这五种IO模型的详细介绍。 一、阻塞IO(Blocking IO) 阻塞IO是最常见、最传统的IO模型。在这种模型…...

基于深度学习的花卉识别系统
简介: 基于Python的花卉识别分类系统利用深度学习和计算机视觉技术,能够准确识别和分类各种花卉,如玫瑰、郁金香和向日葵等。这种系统不仅有助于植物学研究和园艺管理,还在生态保护、智能农业和市场销售等领域展现广泛应用前景。随…...

【斯坦福CS144】Lab0
一、实验目的 1.初步了解计算机网络,准备实验所需的材料和环境; 2.掌握基础实验方法; 3.动手实现网络功能。 二、实验内容 1.下载实验所需的资料,安装虚拟机,配置环境; 2.获取一个网页; …...

关于Mybatis中,IPage<PO>转换成IPage<VO>的问题
以下是一个比较常见通用的一个查询并且为单表查询,在开发初期,或者项目不是很复杂的时候,或者一开始项目框架就规划好的情况下,通常我们都会封装。 在我们的项目中,这部分代码其实是自动生成的,足以满足大…...

使用idea和vecode创建vue项目并启动(超详细)
一、idea创建vue项目 创建项目之前先下载好插件 新建项目找到vue生成器 写好名称,找到自己需要存放的地址,node解释器安装方式可以看我上一个博客,vueCLI是选择vue的版本,我们可以使用idea自带的vue版本默认是vue3,创…...

C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
今天想通过和大家分享如何删除字符串最后一个字符的N种实现方法,来回顾一些基础知识点。 01第一类、字符串方式 这类方法是通过string类型自身方法直接实现。 1、Substring方法 相信大多数人第一个想到的可能就是这个方法。Substring方法是字符串内置方法&#…...

成都睿明智科技有限公司怎么样靠谱吗?
随着短视频与直播的深度融合,抖音电商凭借其强大的流量入口、精准的算法推荐以及便捷的购物体验,迅速崛起。对于传统企业和新兴品牌而言,这无疑是一个不可多得的机遇。然而,如何在这片红海中脱颖而出,就需要借助专业的…...

docker简述
1.安装dockers,配置docker软件仓库 安装,可能需要开代理,这里我提前使用了下好的包安装 启动docker systemctl enable --now docker查看是否安装成功 2.简单命令 拉取镜像,也可以提前下载使用以下命令上传 docker load -i imag…...

第27周:Transformer实战:文本分类
目录 前言 一、前期准备 1.1 环境安装 1.2 加载数据 二、数据预处理 2.1 构建词典 2.2 生成数据批次和迭代器 2.3 构建数据集 三、模型构建 3.1 定义位置编码器 3.2 定义Transformer模型 3.3 初始化模型 3.4 定义训练函数 3.5 定义评估函数 四、训练模型 4.1 模…...

在QT中将Widget提升为自定义的Widget后,无法设置Widget的背景颜色问题解决方法
一、问题 在Qt中将QWidget组件提升为自定义的QWidget后,Widget设置的样式失效,例如设置背景颜色为白色失效。 二、解决方法 将已经提升的QWidget实例对象,脱离父窗体的样式,然后再重新设置自己的样式。...

【学习笔记】手写一个简单的 Spring IOC
目录 一、什么是 Spring IOC? 二、IOC 的作用 1. IOC 怎么知道要创建哪些对象呢? 2. 创建出来的对象放在哪儿? 3. 创建出来的对象如果有属性,如何给属性赋值? 三、实现步骤 1. 创建自定义注解 2. 创建 IOC 容器…...