react基础+pc项目

JSX 注意事项

add

  • class->className
  • for -> htmlFor
  • <></> 幽灵节点
  • JSX 换行需要()包裹

表单组件

  • 受控组件: 被 react 的状态控制的组件

  • input 框自己的状态被 React 组件状态控制

  • 非受控组件

  • 手动操作 dom 的方式获取文本的值

  • createRef

  • myRef.current.value

  • 生成独一无二的 id 可以使用 uuid 包 yarn add uuid

    import { v4 as uuid } from "uuid"
    uuid() // 得到一个独一无二的id

  • 父传子 props 函数
  • 子传父:子组件调用父组件传递过来的函数,并且把想要传递的数据当成函数的实参

兄弟组件通信

  • 通过状态提升机制,利用共同的父组件实现兄弟通信

  • 组件通信-Context 实现跨组件传递数据

  • Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法

  • Provider 提供者 Consumer 消费者

  • 实现步骤

  • 1、创建 Context 对象,导出 Provider 和 Consumer 对象

  • const { Provider,Consumer } = createContext()

  • 2、使用 Provider 包裹跟组件提供数据



  • 3、需要用到数据的组件使用 Consumer 包裹获取数据


    {value => /基于context值进行渲染/}

children 属性

  • 表示该组件的子节点,只有组件内部有子节点,props 中就有该属性
  • children 可以是
  • 1、普通文本
  • 2、普通标签元素
  • 3、函数
  • 4、JSX

props 类型校验

  • 实现步骤

  • 1、安装属性校验包:yarn add prop-types

  • 2、导入 prop-types 包

  • 3、使用组件名.propTypes = {} 给组件添加校验规则

    import PropTypes from "prop-types";
    const list = props => {
    const arr = props.colors
    const lis = arr.map((item,index) =>

  • {item.name}
  • )
    return
      {lis}

    }
    list.propTypes = {
    colors: PropTypes.array
    }

props 校验-规则说明

  • 四种常见结构

  • 1、 常见类型:array、bool、func、number、object、string

  • 2、React 元素类型:element

  • 3、必填项:isRequired

  • 4、特定的结构对象:shape({})

    // 常见类型
    optionalFunc: PropTypes.func
    // 必选
    requiredFunc: PropTypes.func.isRequired
    // 特定结构的对象
    optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
    })

prop 默认值

  • 1、函数组件 使用 defaultProps

    // 设置默认值
    xxx.defaultProps = {
    pageSize: 10

    }

  • 使用函数参数默认值(推荐)

  • 注意:函数组件,新的 react 已经不再推荐 defaultProps 来添加默认值,而是推荐函数参数默认值来实现

  • 区别:第一种在用的时候组件内部已经有了 pageSize 这个 prop 第二种只有传递的时候组件内部才有了 prop

    function List({pageSize = 10}) {
    return(


    )

    }

  • 2、类组件 defaultProps

    xxx.defaultProps = {
    pageSize: 10
    }

  • 使用类静态属性声明

    static defaultProps = {
    pageSize: 10
    }

生命周期

  • 只有类组件才有生命周期(类组件实例化 函数组件不需要实例化)

生命周期-挂载阶段

  • constructor ---> render ---> componentDidMount

  • 1、钩子函数:constructor;触发时机: 创建组件时,最先执行,初始化的时候只执行一次;作用:1.初始化 state 2.创建 Ref 3.使用 bind 解决 this 指向问题等

  • 2、钩子函数:render;触发时机:每次组件渲染都会触发;作用:渲染 UI(注意:不能再里面调用 setState())

  • 3、钩子函数:componentDidMount ;触发时机: 组件挂载(完成 DOM 渲染)后执行,初始化的时候执行一次;作用:1.发送网络请求 2.DOM 操作

生命周期-更新阶段

  • render ---> conponentDidUpdate

  • 1、钩子函数:render; 触发时机:每次组件渲染都会触发;作用: 渲染 UI(与挂载阶段是同一个 render)

  • 2、钩子函数:componentDidUpdate;触发时机:组件更新后(DOM 渲染完毕);作用:DOM 操作,可以获取到更新后的 DOM 内容,不用直接调用 setState

生命周期-卸载阶段

  • componentWillUnmount

  • 1、钩子函数:componentWillUnmount;触发时机:组件卸载(从页面中消失);作用:执行清理工作(比如:清理定时器等)

Hooks 概念理解

1、什么是 hooks

  • Hooks 的本质:一套能够使函数组件更强大,更灵活的“钩子”

  • React 的设计理念UI = f(data)

  • useState

  • useEffect

  • 自定义 hook

  • 自定义一个 hook 函数,实现获取滚动距离的 y

    import { useState } from "react"
    export function useWindowScroll() {
    const [y,setY] = useState(0);
    window.addEventListener('scroll',() => {
    const h = document.documentElement.scrollTop
    setY(h)
    })
    return [y]

    }
    // 引入
    import { useWindowScroll } from "./xxx.js"
    const [y] = useWindowScroll()

  • 自定义 hook 函数,可以自动同步到本地 LocalStorage

  • message 可以通过自定义传入默认初始值

  • 每次修改 message 数据的时候,都会自动往本地同步一份

    import { useEffect, useState } from "react"
    export function useLocalStorage(key,defaultValue) {
    const [message,setMessage] = useState(defaultValue)
    // 每次只要message变化,就会自动同步到本地ls
    useEffect(() =>{
    window.localStorage.setItem(key,message)
    },[message,key])
    return [message,setMessage]
    }
    // 引用
    import { useLocalStorage } from "xxx"
    const [message,setMessage] = useLocalStorage('hook-key','测试')
    setTimeout(() => {
    setMessage('cp)
    },5000)

  • useState -回调函数的参数

  • const [name,setName ] = useState(() => { // 编写计算逻辑 return '计算之后的初始值'})

  • useState(() = > {})

useEffect - 清理副作用

useEffect(() => {
console.log('副作用函数执行了')
// 副作用函数的执行时机为:在下一次副作用函数执行之前执行
return() => {
console.log('清理副作用的函数执行了')
// 在这里写清理副作用的代码
}
})

  • 案例

    function Test() {
    useEffect(() => {
    let timer = setInterval(() => {
    console.log('定时器执行了')
    },1000)
    return () => {
    // 清理的动作
    clearInterval(timer)
    }
    },[])
    }

  • 发送请求

    useEffect(() => {
    async = function fetchData() {
    const res = await axios.get('xxx')
    console.log(res)
    }
    fetchData();
    },[])

useContext

  • 实现步骤

  • 1、使用 createContext 创建 Context 对象

  • 2、在顶层组件通过 Provider 提供数据

  • 3、在底层组件通过 useContext 函数获取数据

  • 代码实现

    import { createContext, useContext } from "react"
    const Context = createContext();
    function Foo() {
    return

    Foo

    }
    function Bar() {
    // 底层组件通过useContext函数获取数据
    const name = useContext(Context);
    return
    Bar {name}

    }
    function App() {
    return (
    // 顶层组件通过Provider提供数据
    <Context.Provider value={'this is name'}>

    </Context.Provider>
    )
    }

  • context 如果要传递的数据,只需要在整个应用初始化的时候传递一次就可以,就可以选择在当前文件(index.js)里做数据提供

  • 如果 context 需要传递数据并且将来还需要在对数据做修改底层组件也需要,跟着一起变,需要写到 app.js
  • 如果提供数据是静态不变-index.js 包裹
  • 如果提供数据需要编号-app.js 可以发便更改数据

React Router V6

1、基础使用

  • 安装 yarn add react-router-dom@6
  • app.jsx

    // 引入必要的内置组件
    import { BrowserRouter, Routes, Route, Link } from "react-router-dom"
    // 准备两个路由组件
    const Home = () =>

    this is home

    const Ablut = () =>
    this is about

    // 进行路由配置
    function App() {
    return(
    // BrowserRouter声明当前要用一个非hash模式的路由

    // Link指定跳转的组件,to用来配置路由地址
    首页
    关于
    // Routes路由出口 路由对应的组件会在这里进行渲染

    // Route指定路径和组件的对应关系,path代表路径 element代表组件成对出现path -> element
    <Route path="/" element={}>
    // /about 可以省略/ /about =about
    <Route path="/about" element={}>


    )
    }

2、核心组件说明

(1)、核心组件-BrowerRouter
  • 作用:包裹整个应用,一个 React 应用只需要使用一次
  • 两种常见 Router: HashRouter 和 BrowserRouter
  • HashRouter: 使用 URL 的哈希值实现(http://localhose:3000/#/first)
  • BrowserRouter: 使用 H5 的 history.pushState API 实现(http://localhose:3000/first)
  • 作用: 用于指定导航链接,完成路由跳转

  • 语法说明:组件通过 to 属性指定路由地址,最终会渲染为 a 链接元素

  • <Link to="/path" >页面一</Link>

(3)、核心组件- Routes
  • 作用:提供一个路由出口,满足条件的路由组件会渲染到组件内部


    // 满足条件的路由组件会渲染到这里


(4)、核心组件- Route
  • 作用:用于指定导航链接、完成路由匹配
  • 语法说明:path 属性指定匹配的路径地址,element 属性指定要渲染的组件
  • <Route path="/about" element={<Ablut />}/>
  • 说明: 当 url 路径为/about时,会渲染 <About />组件

3、编程式导航(跳转与参数)

(1)、编程式导航-跳转
  • 作用:通过 js 编程的方式进行路由页面跳转,比如从登录页跳转到关于页

  • 语法说明:

  • 1、导入 useNavigate 钩子函数

  • 2、执行钩子函数得到跳转函数

  • 3、执行跳转函数完成跳转

  • 注意: 如果在跳转时不想加历史记录,可以添加额外参数 replace 为 true navigate('/about', { replace: true } )

    import { useNavigate } from "react-router-dom"
    const Home = () => {
    //执行函数
    const navigate = useNavigate();
    return (


    Home
    <button onClick={() => navigate('/about')}>跳转关于页

    )
    }
    export default Home

(2)、编程式导航-跳转携带参数
  • 1、searchParams 传参

  • 传参

  • navigate(''/about?id=1001)

  • 取参

  • let [params] = useSearchParams();let id = params.get('id')

  • params 是一个对象,对象里有一个 get 的方法,用来获取对应的参数,把参数的名称作为 get 的实参传过来

  • 2、params 传参

  • 路由传参

  • navigate('/about/1001')

  • 路由取参

  • let params = useParams();let id = params.id

4、嵌套路由

  • 实现步骤

  • 1、App.js 中定义嵌套路由声明

  • 2、Layout 组件内部通过指定二级路由出口

  • App.jsx


    <Route path="/" element={}>
    <Route path="board" element={}>
    <Route path="article" element={

    }>

  • Layout.jsx

    import { Outlet } from "react-router-dom"
    const Layout = () => {
    return(


    layout页面
    // 二级路由的path等于一级path+二级path
    board
    article
    // 二级路由出口


    )
    }
    export default Layout;

默认二级路由
  • 场景:应用首次渲染完毕就需要显示的二级路由
  • 实现步骤
  • 1、给默认二级路由标记 index 属性
  • 把原本的路径 path 属性去掉
  • App.jsx


    <Route path="/" element={}>
    <Route index element={}>
    <Route path="article" element={

    }>

  • Layout.jsx

    import { Outlet } from "react-router-dom"
    const Layout = () => {
    return(


    layout页面
    // 二级路由的path等于一级path+二级path
    board
    article
    // 二级路由出口


    )
    }
    export default Layout;

5、404 页配置

  • 场景:当 url 的路径在整个路由配置中都找不到对应的 path,使用 404 兜底组件进行渲染

  • 1- 准备一个 NotFound 组件

  • NotFound.jsx

    const NotFound = () => {
    return

    this is NotFound

    }

    export default NotFound

  • App.jsx



    <Route path="/" element={}>
    <Route index element={} />
    <Route path="article" element={

    } />

    <Route path="*" element={}>

Mobx

  • 一个可以和 React 良好配合的集中状态管理工具,mobx 和 react 的关系,相当于 vuex 和 vue
  • 同类工具还有:
  • redux
  • dva
  • recoil

Mobx 环境配置

  • Mobx 来做响应式数据建模
  • 1、使用 create-react-app 初始化 react 项目
  • npx create-react-app mobx-react-app
  • 2、安装 mobx 和 mobx-react-lite
  • yarn add mobx mobx-react-lite

Mobx 第一个 store

1、初始化 mobx

  • 初始化步骤

  • 1、定义数据状态(state)

  • 2、在构造器中实现数据响应式处理

  • 3、定义 action 函数(修改数据)

  • 4、实例化 store 并导出

  • counterStore.js

    import { makeAutoObservable } from "mobx"
    class CounterStore {
    count = 0 // 定义数据
    constructor() {
    makeAutoObservable(this) // 响应式处理
    }
    // 定义修改数据的方法
    addCount = () => {
    // 定义action函数
    this.count++
    }
    }
    // 实例化
    const counterStore = new CounterStore();
    export default counterStore

2、React 使用 store

  • 实现步骤
  • 1、导入 store 实例
  • 2、使用 store 中的数据
  • 3、修改 store 中的数据
  • 4、让组件视图响应数据变化
  • App.js

    // 导入counterStore
    import conuterStore from "./store"
    // 导入observer方法
    import { observer } from "mobx-react-lite"
    function App() {
    return(


    <button onClick={() => conuterStore.addCount()}>{conuterStore.count}

    )
    }
    // 包裹组件让视图响应数据变化
    export default observer(App)

3、computed 计算属性

  • 实现步骤
  • 1、声明一个存在的数据
  • 2、定义 get 计算属性
  • 3、在 makeAutoObservable 方法中标记
  • counterStore.js

    import { computed, makeAutoObservable } from 'mobx'

    class CounterStore {
    list = [1, 2, 3, 4, 5, 6]
    constructor() {
    makeAutoObservable(this, {
    filterList: computed
    })
    }
    // 修改原数组
    changeList = () => {
    this.list.push(7, 8, 9)
    }
    // 定义计算属性
    get filterList () {
    return this.list.filter(item => item > 4)
    }
    }

    const counter = new CounterStore()

    export default counter

  • App.js

    // 导入counterStore
    import counterStore from './store'
    // 导入observer方法
    import { observer } from 'mobx-react-lite'
    function App() {
    return (


    {/* 原数组 /}
    {JSON.stringify(counterStore.list)}
    {/
    计算属性 */}
    {JSON.stringify(counterStore.filterList)}
    <button onClick={() => counterStore.changeList()}>change list

    )
    }
    // 包裹组件让视图响应数据变化
    export default observer(App)

4、模块化

  • 实现步骤

  • 1、拆分模块 js 文件,每个模块中定义自己独立的 state/action

  • 2、在 store/index.js 中导入拆分之后的模块,进行模块组合

  • 3、利用 React 的 context 的机制导出统一的 useStore 方法,给业务组件使用

  • 1、定义 task 模块

  • store/taskStore.js

    import { makeAutoObservable } from "mobx"
    class TaskStore{
    taskList = []
    constructor() {
    makeAutoObservable(this)
    }
    addTask() {
    this.taskList.push('vue','react')
    }
    }
    const task = new TaskStore()
    export default tash

  • 2、定义 counterStore

    import { makeAutoObservable } from "mobx"
    class CounterStore{
    count = 0;
    list = [1,2,3,4,5,6]
    constructor() {
    makeAutoObservable(this)
    }
    addCount = () => {
    this.count++
    }
    changeList = () => {
    this.list.push(7,8,9)
    }
    get filterList () {
    return this.list.filter(item => item >4 )
    }
    }
    const counter = new CounterStore();
    export default counter

  • 3、组合模块导出统一方法

  • store/index.js

    import React from "react"
    import counter from "./counterStore"
    import task from "./taskStore"
    class RootStore{
    constructor() {
    this.counterStore = counter
    this.taskStore = task
    }
    }
    const rootStore = new RootStore()
    const context = React.createContext(rootStore)
    const useStore = () => React.useContext(context)
    export

  • 4、组件使用模块中的数据

    import { observer } from "mobx-react-lite"
    // 导入方法
    import { useStore } from "./store"
    function App() {
    // 得到store
    const store = useStore();
    return(


    <button onClick={() => store.counterStore.addCount()}>{store.counterStore.count}

    )
    }
    // 包裹组件让视图响应数据变化
    export default observer(App)

Mobx 基础使用-总结

  • 1、初始化 mobx 的过程是怎样的?
  • 声明数据 ->响应式处理 ->定义 action 函数 ->实例化导出
  • 2、mobx 如何配合 react,需要依赖什么包?
  • mobx-react-lite 作为链接包,导出 observer 方法,包裹组件(只能和函数组件配合)
  • 3、模块化解决了什么问题?
  • 维护性问题
  • 4、如何实现 mobx 的模块化?
  • 按照功能拆分 store 模块,根模块中组合子模块,利用 context 机制依赖注入
react-uuid 创建一个独一无二的 id
  • import uuid from "react-uuid"

Mobx 和 React 职责划分

Store

  • 1、业务状态数据
  • 2、业务状态操作逻辑

React

  • 1、渲染业务数据

  • 2、UI 临时状态维护

  • 3、事件触发,调用 Mobx

  • 富文本编辑器 react-quill

pc 端项目

1、项目技术

  • React 官方脚手架 create-react-app

  • react hooks

  • 状态管理:mobx

  • UI 组件库:antd v4

  • ajax 请求库:axios

  • 路由:react-router-dom 以及 history

  • 富文本编辑器:react-quill

  • CSS 预编译器:sass

    body {
    margin: 0;
    }

    root {

    height: 100%;
    }

2、实现步骤

  • 1、使用 create-react-app 生成项目 npx create-react-app react-demo-pc
  • 2、进入跟目录 cd react-demo-pc
  • 3、启动项目 yarn start

3、 使用 gitee 管理项目

  • 1、在项目根目录打开终端,并初始化 git 仓库(如果已经有了 git 仓库,无需重复该步),命令:git init
  • 2、添加项目内容到暂存区: git add .
  • 3、提交项目内容到仓库区: git commit -m '项目初始化'
  • 4、添加 remote 仓库地址: git remote add origin [gitee 仓库地址]
  • 5、将项目内容推送到 gitee: git push origin master -u // -u 可不传

4、使用 scss 预处理器

  • 1、安装解析 sass 的包: yarn add sass -D
  • 创建全局样式文件: index.scss

5、配置基础路由

  • 1、安装路由:yarn add react-router-dom

  • 2、在 page 目录中创建两个文件夹: Login、Layout

  • 3、分别在两个目录中创建 index.js 文件,并创建一个简单的组件后导出

  • 4、在 App 组件中,导入路由组件以及两个页面的组件

  • 5、配置 Login 和 Layout 的路由规则

  • page/Login/index.js

    const Login = () => {
    return

    login

    }
    export default Login

  • pages/Layout/index.js

    const Layout = () => {
    return

    layout

    }
    export default Layout

  • app.js

    // 导入路由
    import { BrowserRouter, Route, Routes } from 'react-router-dom'

    // 导入页面组件
    import Login from './pages/Login'
    import Layout from './pages/Layout'

    // 配置路由规则
    function App() {
    return (



    <Route path="/" element={}/>
    <Route path="/login" element={}/>



    )
    }

    export default App

6、组件库 antd 使用

  • 1、安装 antd 组件库: yarn add antd

  • 2、全局导入 antd 组件库的样式

  • 3、导入 Button 组件

  • 4、在 Login 页面渲染 Button 组件进行测试

  • src/index.js

    // 先导入 antd 样式文件
    // https://github.com/ant-design/ant-design/issues/33327
    import 'antd/dist/antd.min.css'
    // 再导入全局样式文件,防止样式覆盖!
    import './index.css'

  • pages/Login/index.js

    import { Button } from 'antd'

    const Login = () => (




    )

7、配置别名路径

  • CRA 将所有工程化配置,都隐藏在了 react-scripts 包中,所以项目中看不到任何配置信息

  • 如果要修改 CRA 的默认配置,有以下几种方案:

  • a. 通过第三方库来修改,比如,@craco/craco (推荐)

  • b. 通过执行 yarn eject 命令,释放 react-scripts 中的所有配置到项目中

  • 实现步骤

  • 1、安装修改 CRA 配置的包:yarn add -D @craco/craco

  • 2、在项目根目录中创建 craco 的配置文件:craco.config.js ,并在配置文件中配置路径别名

  • 3、修改package.json中的脚本命令

  • 4、在代码中,就可以通过@来表示 src 目录的绝对路径

  • 5、重启项目,让配置生效

  • craco.config.js

    const path = require('path')

    module.exports = {
    // webpack 配置
    webpack: {
    // 配置别名
    alias: {
    // 约定:使用 @ 表示 src 文件所在路径
    '@': path.resolve(__dirname, 'src')
    }
    }
    }

  • package.json

    // 将 start/build/test 三个命令修改为 craco 方式
    "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
    }

8、@别名路径提示

  • 1、在项目根目录创建jsconfig.json配置文件

  • 2、在配置文件中添加一下配置

  • jsconfig.json

    {
    "compilerOptions": {
    "baseUrl": "./",
    "paths": {
    "@/": ["src/"]
    }
    }
    }

  • vscode 会自动读取 jsconfig.json 中的配置,让 vscode 知道@就是 src 目录

9、路由鉴权实现

  • 实现步骤

  • 1、在 components 目录中,创建 AuthRoute/index.js 文件

  • 2、判断是否登录

  • 3、登录时,直接渲染相应页面组件

  • 4、未登录时,重定向到登录页面

  • 5、将需要鉴权的页面路由配置,替换为 AuthRoute 组件渲染

  • components/AuthRoute/index.js

// 1、判断 token 是否存在
// 2、如果存在 直接正常渲染
// 3、如果不存在 重定向到登录路由
// 高阶组件:把一个组件当初另外一个组件的参数传入 然后通过一定的判断 返回新的组件

import { getToken } from "@/utils"
import { Naviagate } from "react-router-dom"
function AuthRoute({children}) {
const isToken = getToken();
if(isToken) {
return <>{children}</>
}else {
return
}
}
//
// 登录:<></>
// 非登录:
export { AuthRoute }

  • src/app.js

    import { Router, Routes,Route } from "react-router-dom"
    import { AuthRoute } from "@/components/AuthRoute"
    import Layout from "@/page/Layout"
    import Login from "@/pages/Login"

    function App() {
    return(


    /需要鉴权的路由/
    <Route path="/*" element={}/>
    /**不需要鉴权的路由/
    <Route path="/login" element={} />


    )
    }

  • 如何在 react 获取 dom -> useRef

  • 在什么地方获取 dom 节点 -> useEffect

    // 获取频道列表
    const [ channels,setChannels] = useState();
    useEffect(() => {
    async function featchChannels() {
    const res = await http.get('/xxx')
    setChannels(res.data.channels)
    }
    featchChannels();
    }.[])

  • 如果异步请求函数需要依赖一些数据的变化而重新执行, 推荐把它写到内部

  • 统一不抽离函数到外面 只有涉及到异步请求的函数 都放到 useEffect 内部

  • 本质区别:写到外面每次组件更新都会重新进行函数初始化 这本身就是一次性性能消耗,

  • 而写到 useEffect 中 只会在依赖项发生变化的时候 函数才会进行重新初始化

  • 避免性能损失

    // 文章列表管理 统一管理数据 将来修改给setList传对象
    const [list, setList ] = useState({
    list: [], // 文章列表
    count: 0, // 文章数量
    })
    // 文章参数管理
    const [ params, setParams ] = useState({
    page: 1,
    per_page: 10
    })

富文本编辑器

  • 实现步骤

  • 1、安装富文本编辑器:yarn add react-quill

  • 2、导入富文本编辑器组件以及样式文件

  • 3、渲染富文本编辑器组件

  • 4、通过 Form 组件的 initialValues 为富文本编辑器设置初始值,否则会报错

  • 5、调整富文本编辑器的样式

    import React, { useState } from 'react';
    import ReactQuill from 'react-quill';
    import 'react-quill/dist/quill.snow.css';
    function MyComponent() {
    const [value, setValue] = useState('');
    return ;
    }

暂存图片列表实现

问题描述

  • 如果当前为三图模式,已经完成了上传,选择单图只显示一张,再切换到三图继续显示三张,该如何实现?

实现思路

  • 在上传完毕之后通过 ref 存储所有图片,需要几张就显示几张,其实也就是把 ref 当仓库,用多少拿多少

实现步骤

  • 1、通过 useRef 创建一个暂存仓库,在上传完毕图片的时候把图片列表存入

  • 2、如果是单图模式,就从仓库里取第一张图,以数组的形式存入 fileList

  • 3、如果是三图模式,就把仓库里所有的图片,以数组的形式存入 fileList

    const Publish = () => {
    // 1、声明一个暂存仓库
    const fileListRef = useRef([])
    // 2、上传图片时,将所有图片存储到ref中
    const onUploadChange = info => {
    fileListRef.current = imgUrls
    }
    // 3、切换图片类型
    const changeType = e => {
    // 使用原始数据作为判断条件
    const count = e.target.value
    setMaxCount(count)
    if(count === 1) {
    // 单图,只展示第一张
    const firstImg = fileListRef.current[0]
    setFileList(!firstImg ? [] : [firstImg])
    }else if(count === 3) {
    // 三图展示所有图片
    setFileList(fileListRef.current)
    }
    }
    }

  • 获取传参的 id ?id=xxx
  • const [ params ] = useSearchParams();
  • const id = params.get('id')

路由懒加载

使用步骤

  • 1、在 App 组件中,导入 Suspense 组件

  • 2、在路由 Router 内部,使用 Suspense 组件包裹组件内容

  • 3、为 Suspense 组件提供 fallback 属性,指定 loading 占位内容

  • 4、导入 lazy 函数,并修改为懒加载方式导入路由组件

    import { Routes, Route } from 'react-router-dom'
    import { HistoryRouter, history } from './utils/history'
    import { AuthRoute } from './components/AuthRoute'

    // 导入必要组件
    import { lazy, Suspense } from 'react'
    // 按需导入路由组件
    const Login = lazy(() => import('./pages/Login'))
    const Layout = lazy(() => import('./pages/Layout'))
    const Home = lazy(() => import('./pages/Home'))
    const Article = lazy(() => import('./pages/Article'))
    const Publish = lazy(() => import('./pages/Publish'))

    function App () {
    return (

    <Suspense
    fallback={
    <div
    style={{
    textAlign: 'center',
    marginTop: 200
    }}
    >
    loading...

    }
    >

    {/* 需要鉴权的路由 /}
    <Route path="/" element={



    }>
    {/
    二级路由默认页面 /}
    <Route index element={} />
    <Route path="article" element={

    } />
    <Route path="publish" element={} />

    {/
    不需要鉴权的路由 */}
    <Route path='/login' element={} />



    )
    }
    export default App

posted @ 2022-11-22 17:07  不完美的完美  阅读(176)  评论(0)    收藏  举报