react项目--博客管理

文章目录

  • 技术栈
  • 登录存信息
  • 配置token
  • hooks使用
  • 路由配置
  • 各页面技术总结
    • 首页
    • 发布文章
    • 文章详情页
  • 个人主页
  • 分类页

本篇文章总结一个开发的react项目—博客系统

技术栈

React、react-redux、react-router 6,Ant Design,es6,sass,webpack

登录存信息

在这里插入图片描述

主要业务逻辑:redux存信息
redux如何使用,可以看这篇博客 redux使用
创建一个store文件夹
在这里插入图片描述
在index.js文件夹里面写总代理

import { configureStore } from "@reduxjs/toolkit"; // configureStore (): 包装 createStore 以提供简化的配置选项和良好的默认设置。它可以自动组合你的slice reducers,添加你提供的任何 Redux 中间件,默认包括 Redux-thunk,并启用 Redux DevTools 扩展。
import userReducer from "./modules/user";export default configureStore({reducer:{user:userReducer}
})

在user.js里面写用户的状态管理

首先导入createSlice,用于接受 reducer 函数的对象、片名和初始状态值,并自动生成带有相应动作创建器和动作类型的 slice reducer。

import { createSlice } from "@reduxjs/toolkit";
import { setToken as _setToken,getToken, removeToken } from "@/utils";
import { loginAPI,getProfileAPI } from "@/apis/user"; //导入需要的其他api

const userStore = createSlice({
}),在createSlice写主要逻辑
定义数据状态

 initialState:{token:getToken() || '',userInfo:{}},

编写reducer逻辑

reducers:{setToken(state,action){state.token = action.payload_setToken(action.payload)//action.payload是这个action重新包装后的return返回结果,是createSlice特有的},setUserInfo(state,action){state.userInfo=action.payload},clearUserInfo(state){state.token = ''state.userInfo = {}removeToken()} }
//解构出actionCreater
const { setToken,setUserInfo,clearUserInfo } =userStore.actions

调用接口,获取数据

//异步请求const fetchLogin = (loginForm) =>{return async (dispatch)=>{const res = await loginAPI(loginForm)dispatch(setToken(res.data.token))}
}
//....其余获取个人信息的相关接口

导出reducer函数和封装的函数

//获取reducer函数
const userReducer = userStore.reducerexport {setToken,fetchLogin,fetchUserInfo,clearUserInfo}export default userReducer

完整的redux就是这些了

配置token

在专门文件里面封装token配置

在这里插入图片描述

//封装token方法const TOKENKEY='token_key'function setToken(token){localStorage.setItem(TOKENKEY,token)
}function getToken(){return localStorage.getItem(TOKENKEY)
}function removeToken(){localStorage.removeItem(TOKENKEY)
}export{setToken,getToken,removeToken
}

hooks使用

详细hooks可看这篇文章:react—hooks

获取列表示例,展示如何使用hooks

//获取频道列表的逻辑
import { useState,useEffect } from "react"
import { getChannelAPI }from '@/apis/article'function useChannel(){const [channelList, setChannels] = useState([])// 调用接口useEffect(() => {const getChannelList = async () => {const res = await getChannelAPI()setChannels(res.data.channels)}getChannelList()}, [])return {channelList}
}export {useChannel}

路由配置

配置路由守卫,无token信息跳转登录页

import { getToken } from '@/utils'
import { Navigate } from 'react-router-dom'const AuthRoute = ({ children }) => {const isToken = getToken()if (isToken) {return <>{children}</>} else {return <Navigate to="/login" replace />}
}export default AuthRoute

基本路由配置

import AuthRoute from "@/components/AuthRoute";import { Suspense, lazy } from "react";
//<Suspense> 允许在子组件完成加载前展示后备方案。lazy 就是懒加载
import { createBrowserRouter } from "react-router-dom"; //创建路由
//createBrowserRouter底层是用到了h5的新特性history,这个方法可以实现修改地址栏地址而不会向后端发起请求,并且history这个对象本身就提供了很多控制页面跳转,前进后退等方法。而createHashRouter则是利用了锚点跳转不发起请求的特点,也就是你在网络地址后面加 上#,#后面的内容无论怎么改变都不会引起浏览器发起网络请求,然后通过监听onhashchange事件来监听这个锚点的变化,以此来匹配配置的路由。//路由懒加载
const Home = lazy(()=>import('@/pages/Home'))
const Acticles = lazy(()=>import('@/pages/Acticles'))
//....其余路由```javascript
const router= createBrowserRouter([{path:"/",element:<AuthRoute> <Layout/> </AuthRoute>,// 路由守卫嵌套children:[{path:'all',element:<Suspense fallback={'加载中'}><Home/></Suspense>,children:[{index:true, //默认加载路由element:<Suspense fallback={'加载中'}><All/></Suspense> }, ...........其余配置

在页面设置路由出口

import { Outlet } from 'react-router-dom'
<div style={{backgroundColor:'white'}}><Menumode="horizontal"selectedKeys={selectkey}onClick={onMenuClick}items={items}></Menu><Outlet></Outlet> //设置子路由出口</div>)

各页面技术总结

首页

利用useLocation进行反向高亮

 //反向高亮const location = useLocation();const selectkey  =location.pathname//触发个人信息的actionconst dispatch = useDispatch()useEffect(()=>{dispatch(fetchUserInfo())},[dispatch])
//获取store内的个人信息const name= useSelector(state=>state.user.userInfo.name)

在这里插入图片描述
选择时,高亮效果没实现,增加以下两行代码

const isHomeSelected = location.pathname.startsWith('/all');
selectedKeys={[isHomeSelected ? '/all' : selectkey]}

发布文章

回填数据

const [searchParams]=  useSearchParams()const articleId  =searchParams.get('id')// console.log(articleId);const [form]= Form.useForm()useEffect(()=>{//通过id获取数据async function getArticleDetail(){const res=  await getArticleById(articleId)const data = res.dataform.setFieldsValue({...data,type:data.cover.type,})//回填图片列表setImageType(data.cover.type)setImageList(data.cover.images.map(url=>{return {url}}))}//只有有id才能回填if(articleId){getArticleDetail()}},[articleId,form])

文章详情页

在这里插入图片描述
内容是html形式,转化为文本类型,封装了一个函数

 function removeHTMLTags(html) {const doc = new DOMParser().parseFromString(html, 'text/html');return doc.body.textContent || '';}

个人主页

在这里插入图片描述
先调用redux里面的方法 ,获取个人信息

useEffect(() => {dispatch(fetchUserInfo());}, [dispatch]);

问题:由于使用了一次useEffect,当页面再次渲染时,数据回填不上
解决方法:
进行if判断,有id机进行回填,实现异步操作

useEffect(()=>{if (data) {//进行数据回填form.setFieldsValue({ name, gender: gender === 0 ? '男' : '女', intro });//回填照片console.log(photo);let url = [{uid: '-1',name: 'image1.png',status: 'done',url:data.photo,description: '这是第一张图片'}]console.log(url);setImageUrl(url)}},[data])

问题:生日时间第一次获取到null,数据回填成默认形式,不是应有的数据
解决方法:

//在组件内设置key,当key里面值变化时,组件重新渲染
<Form.Itemlabel="生日"><DatePicker defaultValue={defaultValue} key={defaultValue} onChange={getDate} /></Form.Item>

问题:头像设置问题,在有头像时,不显示上传部分
解决方法:

//用三元表达式进行判断
<Uploadname="avatar"listType="picture-circle"className="avatar-uploader"showUploadListaction="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"onChange={onChange}maxCount={1}fileList={imageUrl}>{count===0?<div style={{ marginTop: 8 }}><PlusOutlined /></div>:''}</Upload>

分类页

在这里插入图片描述
由于页面一样,数据不一样,先封装个模板,等待传来的参数
在这里插入图片描述

const Item = (props) => {//得到传来的listconst { parameter } = props;// console.log('/',parameter);const navigate = useNavigate().....其余代码}

问题:分类是根据标签列表实现的,所以要先进行判断,以前端页面举例

const Before=()=>{const [belist,setBelist] = useState([])//判断getList().then(res=>{let list = res.filter((item)=>{return item.channel_id===1 || item.channel_id===6 || item.channel_id===15 || item.channel_id===17 || item.channel_id===23})setBelist(list)})return (<div>//传参<Item parameter= {belist}></Item></div>)}

其他页面类似

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/851057.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RPA-UiBot6.0数据整理机器人—杂乱数据秒变报表

前言 友友们是否常常因为杂乱的数据而烦恼?数据分类、排序、筛选这些繁琐的任务是否占据了友友们的大部分时间?这篇博客将为友友们带来一个新的解决方案,让我们共同学习如何运用RPA数据整理机器人,实现杂乱数据的快速整理,为你的工作减负增效! 在这里,友友们将了…

成功解决No module named ‘sklearn’(ModuleNotFoundError)

成功解决No module named ‘sklearn’(ModuleNotFoundError) &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f…

AI 边缘计算平台 - 回归开源 BeagleY-AI 简介

BeagleBoard.org 于 3 月 27 号发布了一款单板计算机 BeagleY-AI &#xff0c;这款 SBC 凭借其完全开源的特性&#xff0c;旨在激发并推动开源社区的生态系统繁荣发展。 一、简介&#xff1a; BeagleY-AI 采用德州仪器新推出的 AM67A AI 视觉处理器。这款处理器集成了四个 64…

开源模型应用落地-LangChain高阶-LCEL-表达式语言(五)

一、前言 尽管现在的大语言模型已经非常强大,可以解决许多问题,但在处理复杂情况时,仍然需要进行多个步骤或整合不同的流程才能达到最终的目标。然而,现在可以利用langchain来使得模型的应用变得更加直接和简单。 LCEL是什么? LCEL是一种非常灵活和强大的语言,可以帮助您更…

UE5基础1-下载安装

目录 一.下载 二.安装 三.安装引擎 四.其他 简介: UE5&#xff08;Unreal Engine 5&#xff09;是一款功能极其强大的游戏引擎。 它具有以下显著特点&#xff1a; 先进的图形技术&#xff1a;能够呈现出令人惊叹的逼真视觉效果&#xff0c;包括高逼真的光影、材…

Redis原理篇——哨兵机制

Redis原理篇——哨兵机制 1.Redis哨兵2.哨兵工作原理2.1.哨兵作用2.2.状态监控2.3.选举leader2.4.failover 1.Redis哨兵 主从结构中master节点的作用非常重要&#xff0c;一旦故障就会导致集群不可用。那么有什么办法能保证主从集群的高可用性呢&#xff1f; 2.哨兵工作原理 …

备战 清华大学 上机编程考试-冲刺前50%,倒数第4天

T1:四操作 有一个n个元素的数列,元素的值只能是0 1 2三个数中的一个&#xff0c;定义四种操作&#xff0c;(1 i x)表示为把第i位替换成x&#xff0c;x也只能是0 1 2三个数中的一个&#xff0c;(2 i j)表示把第i个数到第j个数所有的元素值加1&#xff0c;并对3取模&#xff0c;…

【JS重点06】作用域(面试重点)

目录 一:局部作用域 1 函数作用域 2 块作用域 二:全局作用域 三:作用域链 变量查找机制: 本文章目标:了解作用域对程序执行的影响及作用域链的查找机制 作用域:规定了变量能够被访问的”范围“,离开这个”范围“变量便不能被访问 一:局部作用域 局部作用域分为…

CDR2024软件破解Keygen激活工具2024最新版

CorelDRAW Graphics Suite2024最新版&#xff0c;这是一款让我爱不释手的图形设计神器&#xff01;作为一个软件评测专家&#xff0c;我一直在寻找一款能够提升我的设计效率和创造力的工具。而这款软件&#xff0c;简直就是为我量身定制的&#xff01;&#x1f389; 「CorelDR…

C#进阶高级语法之LINQ

&#x1f433;简介 LINQ是C#编程语言中的一项强大功能&#xff0c;它通过将查询直接集成到编程语言中&#xff0c;大幅度简化了数据查询的代码编写工作。 LINQ的应用场景&#xff1a; 数据源支持&#xff1a;LINQ可查询的数据源类型极为广泛&#xff0c;包括SQL Server数据库…

插卡式仪器模块:示波器模块(插卡式)

• 12 位分辨率 • 125 MSPS 采样率 • 支持单通道/双通道模块选择 • 可实现信号分析 • 上电时序测量 • 抓取并分析波形的周期、幅值、异常信号等指标 • 电源纹波与噪声分析 • 信号模板比对 • 无线充电&#xff08;信号解调&#xff09; 通道12输入阻抗Hi-Z, 1 MΩ…

检索增强生成RAG需要用到的10个资源、工具和Python库

●10个资源和工具 在机器学习和自然语言处理领域&#xff0c;有多种工具和框架可用于实现和使用检索增强型生成&#xff08;RAG&#xff09;模型。以下是一些关键的资源和工具&#xff1a; Hugging Face Transformers&#xff1a; Hugging Face在其广泛使用的Transformers库…

CountDownLatch闭锁

Java并发库提供了CountDownLatch类来实现这个功能。 CountDownLatch类是一个同步工具类&#xff0c;在完成某些运算时&#xff0c;只有其他所有的运算全部完成&#xff0c;当前运算才继续执行。 下面是一个案例来说明CountDownLatch&#xff1a; 说明&#xff1a;当前有 5 个…

matlab使用教程(95)—显示地理数据

下面的示例说明了多种表示地球地貌的方法。此示例中的数据取自美国商务部海洋及大气管理局 (NOAA) 国家地理数据中心&#xff0c;数据通告编号为 88-MGG-02。 1.关于地貌数据 数据文件 topo.mat 包含地貌数据。topo 是海拔数据&#xff0c;topomap1 是海拔的颜色图。 load t…

java-ArrayList的底层原理

Java中的ArrayList是基于数组实现的动态数组&#xff0c;它提供了比标准数组更多的灵活性&#xff0c;特别是在大小方面。ArrayList的底层原理主要依赖于以下几个关键点&#xff1a; 1. 数组&#xff1a;ArrayList内部维护了一个数组&#xff0c;这个数组用于存储集合中的元素。…

nodejs 中 axios 设置 burp 抓取 http 与 https

在使用 axios 库的时候&#xff0c;希望用 burp 抓包查看发包内容。但关于 axios 设置代理问题&#xff0c;网上提到的一些方法不是好用&#xff0c;摸索了一段时间后总结出设置 burp 代理抓包的方法。 nodejs 中 axios 设置 burp 抓包 根据请求的站点&#xff0c;分为 http …

web前端:作业二

<!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 1.将ul的子l…

Java加密体系结构参考指南-Java Cryptography Architecture

本文是从英文的官网摘了翻译的&#xff0c;用作自己的整理和记录。水平有限&#xff0c;欢迎指正。版本是&#xff1a;22 原文地址&#xff1a;https://docs.oracle.com/en/java/javase/22/security/java-cryptography-architecture-jca-reference-guide.html#GUID-815542FE-CF…

JavaScript学习|JavaScript 引入方式、JavaScript 基础语法、JavaScript 对象、BOM、DOM、事件监听、事件绑定

JavaScript 能做什么 1.能够改变文本内容 2.能够改变图像的src属性值 3.能够进行表单验证等 JavaScript 引入方式 内部脚本 1.内部脚本:将 JS代码定义在HTML页面中&#xff0c;JavaScript代码必须位于<script>与</script>标签之间。在 HTML 文档中可以在任意地…

C/C++学习笔记 C语言中的\0以及查找字符串中字符出现的频率

在此示例中&#xff0c;计算了字符串对象中字符的频率。 为此&#xff0c;使用size()函数查找字符串对象的长度。然后for 循环迭代直到字符串末尾。 在每次迭代中&#xff0c;检查字符是否出现&#xff0c;如果发现&#xff0c;则计数增加 1。 示例 1 #include <iostream&g…