20230608----重返学习-react项目的细节

news/2024/10/31 3:22:41/

day-088-eighty-eight-20230608-react项目的细节

react项目的细节

进入登录页的情况分析

  • 什么情况下,会进入登录页?
    1. 手动输入 /login 地址http://127.0.0.1:3000/#/login

      • 登录成功:跳转到首页push()
    2. 我原本想进入的是 个人中心/我的收藏/修改个人信息页,但是经过登录态校验,发现我没有登录,则跳转到登录页

      • 虽然没有渲染真正的个人中心等组件,但是路由匹配后,渲染了Element这个统一处理的组件 —> 历史记录已经有了
      • 个人中心 /personal replace到登录页
      • 跳转到登录页 /login?to=/personal replace到来源页
        • 登录成功{之前想去哪,我们应该让其直接跳转到哪} /personal
    3. 在新闻详情页,我们点击收藏按钮,但因为没有登录,需要跳转到登录页

      • /detail/xxx replace到登录页
      • /login?to=/detail/xxx replace到来源页
      • /detail/xxx 会记录下当前页。

点击返回组件的情况分析

  • 返回组件:
    • 点击返回时:
      • 如果有to的查询字符串,就替换到to对应的页面。
      • 如果没有to的查询字符串,就不替换。
      • 所以才要把返回功能封装成一个组件。
    • 样式是独立的,内部的组件可以使用。

一个常规进入登录页的流程

  • 直接输入登录页
  • 手动输入登录页地址
  • 进入个人中心但没登录
  • 在非权限页点击需要登录才能进行的操作跳转到的登录页
  • 点击退出登录页才进入的登录页(这个可能会有几个路由记录都是需要登录才能进的页面)

收藏功能

  • 因为收藏功能是需要在应用整个周期中记录信息的,所以要放全局状态中管理。
    • 因为刷新时要更新到最新的数据,同步来自其它终端的数据,放到本地存储时难以及时更新。
  • 所以在redux仓库对应的store文件夹设置一个收藏相关的模块中。
    • 实际上,仅仅收藏只是放在用户信息中。但这里为了演示另一个独立模块,所以单独把收藏的功能放在这。
      • 功能有查询收藏列表、新增单个收藏、减少单个收藏

个人中心页

  • fang/知乎日报/zhihu/src/views/Personal.jsx
// import { message } from "react";
import message from "@/components/message";
import styled from "styled-components";
import { Link } from "react-router-dom";
import { RightOutline } from "antd-mobile-icons";
import NavBarAgain from "@/components/NavBarAgain";import { connect } from "react-redux";
import action from "@/store/actions";
import _ from "@/assets/utils";/* 组件的样式 */
const PersonalStyle = styled.div`.baseInfo {box-sizing: border-box;margin: 20px 0;.pic {display: block;margin: 0 auto;width: 86px;height: 86px;border-radius: 50%;}.name {line-height: 50px;font-size: 18px;text-align: center;color: #000;}}.tab {display: flex;justify-content: space-between;align-items: center;padding: 0 15px;height: 40px;line-height: 40px;font-size: 14px;color: #000;border-bottom: 1px solid #eee;}
`;const Personal = function Personal({navigate,profile,removeLoginInfo,clearStore,
}) {return (<PersonalStyle><NavBarAgain title="个人中心" /><div className="baseInfo"><Link to="/update"><img className="pic" src={profile.pic} alt={profile.name} /><p className="name">{profile.name}</p></Link></div><div><Link to="/mystore" className="tab">我的收藏<RightOutline /></Link><divclassName="tab"onClick={() => {removeLoginInfo();clearStore();_.storage.remove(`TK`);message.success(`已安全退出`);navigate(`/login?to=/personal&lx=singout`, { replace: true });}}>退出登录<RightOutline /></div></div></PersonalStyle>);
};
export default connect((state) => state.base, {removeLoginInfo: action.base.removeLoginInfo,clearStore: action.collect.clearStore,
})(Personal);

退出登录的返回上一级路由逻辑

  • fang/知乎日报/zhihu/src/components/NavBarAgain.jsx

    import React from "react";
    import { NavBar } from "antd-mobile";
    import styled from "styled-components";
    import { useNavigate, useSearchParams } from "react-router-dom";/* 组件的样式 */
    const NavBarAgainStyle = styled.div`.navbar-again-box {padding: 0 10px;height: 40px;.adm-nav-bar-title {font-size: 16px;}.adm-nav-bar-back-arrow {font-size: 18px;}}
    `;const NavBarAgain = function NavBarAgain({ title }) {const navigate = useNavigate();const query = useSearchParams()[0];const handle = () => {// console.log(`query`, query);let to = query.get("to");let lx = query.get("lx");if (/^\/detail\//.test(to)) {navigate(to, { replace: true });return;}if (to === `/personal` && lx === `singout`) {//点击退出登录才进入的登录页。//因为退出登录之前,有可能进的还是需要权限校验的的地方,不会在退出登录时循环校验。navigate(`/`, { replace: true });return;}navigate(-1);};return (<NavBarAgainStyle><NavBar className="navbar-again-box" onBack={handle}>{title}</NavBar></NavBarAgainStyle>);
    };
    NavBarAgain.defaultProps = {title: "个人中心",
    };
    export default NavBarAgain;
    

图片的上传及修改

  • fang/知乎日报/zhihu/src/views/Update.jsx
// import { useState, message } from "react";
import { useState } from "react";
import message from "@/components/message";
import styled from "styled-components";
import { ImageUploader, Input, Button } from "antd-mobile";
import NavBarAgain from "@/components/NavBarAgain";import { connect } from "react-redux";
import action from "@/store/actions";
import API from "@/api";import ButtonAgain from "@/components/ButtonAgain";/* 组件的样式 */
const UpdateStyle = styled.div`.formBox {padding: 15px;.item {display: flex;align-items: center;margin-bottom: 10px;height: 55px;line-height: 55px;font-size: 14px;&:nth-child(1) {height: 80px;line-height: 80px;}.label {width: 20%;text-align: center;}.input {width: 80%;}}.adm-space-item {padding-bottom: 0;}}.submit {display: block;margin: 0 auto;width: 60%;height: 35px;font-size: 14px;}
`;const Update = function Update({ profile, queryLoginInfo, navigate }) {// 图片上传的处理。let [fileList, setFileList] = useState(() => {return [{url: profile.pic,},];});//   清空已上传的图片。const handleDelete = () => {setFileList([]);};// 上传图片前:限制文件大小。const beforeUpload = (file) => {// console.log("beforeUpload", file);let theMax = 1024 * 1024;if (file.size > theMax) {message.error(`上传图片过大,不能超过${theMax / 1024}kb`);return null;}return file;};// 图片上传。//   const upload = async (file) => {//     // console.log("upload", file);//     let result = { url: `` };//     try {//       let { code, pic } = await API.upload(file);//       if(+code===0)//       if (+code !== 0) {//         message.error(`上传失败`);//         setFileList([]);//       } else {//         message.success(`上传成功`);//         setFileList([{ url: pic }]);//         result.url = pic;//       }//     } catch (_) {}//     return result;//   };// 图片上传。const upload = async (file) => {try {let { code, pic } = await API.upload(file);if (+code === 0) {message.success(`上传成功`);setFileList([{ url: pic }]);return { url: pic };}message.success(`上传失败`);} catch (_) {}setFileList([]);return Promise.reject(`失败`);};// 表单处理。let [name, setName] = useState(profile.name);const submit = async () => {let username = name.trim();let pic = ``;if (Array.isArray(fileList) && fileList.length > 0) {pic = fileList[0].url;}//表单校验// console.log(username ,pic);if (!username || !pic) {message.error(`姓名与头像不能为空`);return;}// 发送请求try {let { code } = await API.updateUserInfo(username, pic);if (+code !== 0) {message.error(`修改失败`);return;}await queryLoginInfo();message.success(`修改成功`);navigate(-1);} catch (error) {}};return (<UpdateStyle><NavBarAgain title="修改信息" /><div className="formBox"><div className="item"><div className="label">头像</div><div className="input"><ImageUploadermaxCount={1}value={fileList}onDelete={handleDelete}beforeUpload={beforeUpload}upload={upload}showFailed={false}/></div></div><div className="item"><div className="label">姓名</div><div className="input"><Inputplaceholder="请输入账号名称"value={name}onChange={(value) => {setName(value);}}/></div></div><ButtonAgain color="primary" className="submit" onClick={submit}>提交</ButtonAgain></div>{/* 当前图片状态值:{JSON.stringify(fileList)} */}</UpdateStyle>);
};
export default connect((state) => state.base, action.base)(Update);

进阶参考


http://www.ppmy.cn/news/305202.html

相关文章

Pascal Voc 2007 2012

1、简介 PASCAL 全称&#xff1a;Pattern Analysis, Statical Modeling and Computational Learning PASCAL VOC&#xff08;The PASCAL Visual Object Classes &#xff09;是一个经典的计算机视觉数据集&#xff0c;由牛津大学、马里兰大学和微软剑桥研究院的研究人员创建的…

[开发|java] com.typesafe.config配置示例说明

com.typesafe.config库是用于处理配置文件的Java库&#xff0c;它提供了一种方便的方式来读取和解析配置文件。要配置时间配置&#xff0c;你可以使用它的Config对象和相关的方法。 官方文档地址 下面是一个示例&#xff0c;演示如何使用com.typesafe.config库来配置时间配置&…

从QGIS图层中裁剪需要的区域

GiS数据裁切&#xff0c;创建一个临时图层&#xff0c;通过矢量裁切的方法&#xff0c;将Gis图层进行裁切&#xff1b;影像裁切&#xff0c;将影像图层放置在Gis中&#xff0c;截取影像图以及临时图层的轮廓&#xff0c;放入PS中进行对比&#xff0c;然后将影像图裁切下来。 1…

升级了显卡驱动,Vista得分从3.1提升到3.5,高兴啊!:)

我的是昭阳K42A笔记本&#xff0c;显卡是Nvidia Geforce8400M GS&#xff0c;升级了最新的修改版驱动&#xff1a;NVIDIA_XTreme-G_162.62mb_vista32&#xff0c;下载地址是&#xff1a;http://count.mydrivers.com/download.aspx?id77223&urlhttp://file5.mydrivers.com/…

新买了一个本

本想买Thinkpad T61的水货&#xff0c;都看好了AR1和A24这两款&#xff0c;昨天跑到市场去看了下真机&#xff0c;感觉外壳做工很粗糙&#xff0c;不是很满意&#xff0c;最后综合考虑入手了联想昭阳K42A&#xff0c;用了一天多了&#xff0c;感觉不错&#xff0c;性能很好&…

xp 下启用 ahci 模式

windows XP系统下如何开启AHCI硬盘工作模式&#xff08;XP系统下如何加载AHCI驱动&#xff09; 转自&#xff1a; http://support1.lenovo.com.cn/lenovo/wsi/htmls/detail_12608719119063756.html 问题描述 用户来电表示使用IDE模式安装XP系统后开启AHCI模式会出现开机蓝屏重启…

【转】XP开机启动一直停留在滚动条界面的解决方案

开机启动界面,一直滚一直滚,就是不进系统!!!郁闷!!! 下面是我自己摸索出来的方法,大家不要搞错了哦! 1、未加载AHCI驱动(已安装芯片组驱动)时设备管理器截图2、下载SATA驱动并解压缩 (下面附件里面)

【Python程序设计】——重点题目(期末不挂科)

课本&#xff1a; 目录 &#x1f552; 1. 控制结构&#x1f552; 2. 数据类型&#x1f552; 3. 函数&#x1f552; 4. 文件操作&#x1f552; 5. 面向对象&#x1f552; 6. Excel操作&#x1f552; 7. 实验课题目合集&#x1f552; 8. 思政题 &#x1f552; 1. 控制结构 【例…