React-Hooks 和 React-Redux

注:Redux最新用法参考 个人React专栏 react 初级学习

Hooks基本介绍-------------------------

  • Hooks:钩子、钓钩、钩住, Hook 就是一个特殊的函数,让你在函数组件中获取状态等 React 特性 ,是 React v16.8 中的新增功能

  • 作用:为函数组件提供状态、生命周期等原本 class 组件中提供的 React 功能

    • 可以理解为通过 Hooks 为函数组件钩入 class 组件的特性

  • 注意:Hooks 只能在函数组件中使用,自此,函数组件成为 React 的新宠儿

React v16.8 版本前后,组件开发模式的对比:

  • React v16.8 以前: class 组件(提供状态) + 函数组件(展示内容)

  • React v16.8 及其以后:

    1. class 组件(提供状态) + 函数组件(展示内容)

    2. Hooks(提供状态) + 函数组件(展示内容)

    3. 混用以上两种方式:部分功能用 class 组件,部分功能用 Hooks+函数组件

总结

注意1:虽然有了 Hooks,但 React 官方并没有计划从 React 库中移除 class

注意2:有了 Hooks 以后,不能再把函数组件称为无状态组件了,因为 Hooks 为函数组件提供了状态

为什么要有 Hooks

  • 组件的状态逻辑复用
    • 在 Hooks 之前,组件的状态逻辑复用经历了:mixins(混入)、HOCs(高阶组件)、render-props 等模式

    • (早已废弃)mixins 的问题:1 数据来源不清晰 2 命名冲突

    • HOCs、render-props 的问题:重构组件结构,导致组件形成 JSX 嵌套地狱问题

  • class 组件自身的问题
    • 选择:函数组件和 class 组件之间的区别以及使用哪种组件更合适

    • 需要理解 class 中的 this 是如何工作的

    • 相互关联且需要对照修改的代码被拆分到不同生命周期函数中

    • 相比于函数组件来说,不利于代码压缩和优化,也不利于 TS 的类型推导

注意:

之前的react语法并不是以后就不用了,class 组件相关的 API 在hooks中可以不用

  • class 自身语法,比如,constructor、static 等
  • 钩子函数,componentDidMountcomponentDidUpdatecomponentWillUnmount
  • this 相关的用法

useState-Hooks

useState-基本使用

  • useState作用:为函数组件提供状态(state),不能在类组件中调用

  • useState使用场景:当你想要在函数组件中,使用组件状态时,就要使用 useState Hook 了

  • 约定:修改状态的函数名称以 set 开头,后面跟上状态的名称

  • 多次调用 useState 多个状态和修改状态的函数之间不会相互影响

  • useState 提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用

  • 每次渲染,useState 获取到的都是最新的状态值(react会记住最新的状态值),useState 的初始值(参数)只会在组件第一次渲染时生效

语法:

import { useState } from 'react'// 参数:状态初始值可以是任意值
// 返回值:stateArray 是一个数组
const stateArray = useState(0)// 索引 0 表示:状态值(state)
const state = stateArray[0]
// 索引 1 表示:修改状态的函数(setState(newValue)` 是一个函数,参数表示:*新的状态值*)
const setState = stateArray[1]

状态的读取和修改:

  • 读取状态

const Counter = () => {
  const [user, setUser] = useState({ name: 'jack', age: 18 })
  
  return (
      <div>
        <p>姓名:{user.name}</p>
            <p>年龄:{user.age}</p>
    </div>
  )
}

  • 修改状态
    • 调用该函数后,将使用新的状态值替换旧值
    • 修改状态后,因为状态发生了改变,所以,该组件会重新渲染
    • setUser(newValue) 是一个函数,参数表示:新的状态值 。调用这个函数,新的状态值会覆盖原来的状态值,所以,这里和class的setState不一样,区分一下,class的setState需要修改哪个值就传哪个值,内部会做状态的合并,hooks呢修改状态值会直接覆盖不会合并,所以hooks修改状态值需要先对原来的值进行取值解构,再修改。
const Counter = () => {// 利用数组解构提取状态和修改状态const [user, setUser] = useState({ name: 'jack', age: 18 })const onAgeAdd = () => {setUser({...user,age: user.age + 1})}return (<div><p>姓名:{user.name}</p><p>年龄:{user.age}</p><button onClick={onAgeAdd}>年龄+1</button></div>)
}

useState-使用规则

  • 如何为函数组件提供多个状态?

    • 调用 useState Hook 多次即可,每调用一次 useState Hook 可以提供一个状态

    • useState Hook 多次调用返回的 [state, setState],相互之间,互不影响

  • useState 等 Hook 的使用规则:

    • React Hooks 只能直接出现在 函数组件 中

    • React Hooks不能嵌套在 if/for/其他函数 中

    • 原理:React 是按照 Hooks 的调用顺序来识别每一个 Hook,如果每次调用的顺序不同,导致 React 无法知道是哪一个 Hook

useEffect-Hooks

useEffect-基本含义

  • 作用:处理函数组件中的副作用(side effect)
  • 副作用是相对于主作用来说的,一个功能(比如,函数)除了主作用,其他的作用就是副作用 对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
  • 常见的副作用(side effect):数据(Ajax)请求、手动修改 DOM、localStorage、console.log 操作等
  • useEffect完全指南:useEffect 完整指南 — Overreacted

useEffect-基本使用

  • 使用时机

import { useEffect } from 'react'// 1 
// 触发时机: 第一次渲染会执行 、 每次组件重新渲染都会再次执行
// componentDidMount + ComponentDidUpdate
useEffect(() => {})// 2(使用频率最高)
// 触发时机:只在组件第一次渲染时执行
// componentDidMount
useEffect(() => {}, [])// 3(使用频率最高)
// 触发时机:1 第一次渲染会执行 2 当 count(某个状态) 变化时才会次执行
// componentDidMount + componentDidUpdate(判断 count 有没有改变)
useEffect(() => {}, [count])// 4
useEffect(() => {// 返回值函数的执行时机:组件卸载时// 在返回的函数中,清理工作return () => {// 相当于 componentWillUnmount}
}, [])//5
useEffect(() => {// 返回值函数的执行时机:1 组件卸载时 2 count 变化时// 在返回的函数中,清理工作return () => {}
}, [count])
  • 发送请求

  • 在组件中,可以使用 useEffect Hook 来发送请求(side effect)获取数据

  • 注意:effect 只能是一个同步函数,不能使用 async

    • 因为如果 effect 是 async 的,此时返回值是 Promise 对象。这样的话,就无法保证清理函数被立即调用

  • 为了使用 async/await 语法,可以在 effect 内部创建 async 函数,并调用

// 错误演示:不要给 effect 添加 async
useEffect(async () => {const res = await axios.get('http://xxx')return () => {}
}, [])// 正确使用
useEffect(() => {const loadData = async () => {const res = await axios.get('http://xxx')}loadData()return () => {}
}, [])

useContext-Hooks

作用

  • 在函数组件中,获取 Context 中的值。要配合 Context 一起使用。

语法

  • useContext 的参数:Context 对象,即:通过 createContext 函数创建的对象

  • useContext 的返回值:Context.Provider 中提供的 value 数据

import { useContext } from 'react'const { color } = useContext(ColorContext)

useContext Hook<Context.Consumer> 的区别:获取数据的位置不同

  • <Context.Consumer>:在 JSX 中获取 Context 共享的数据

  • useContext:在 JS 代码 或者 JSX 中获取 Context 的数据

const ColorContext = createContext()const Child = () => {// 在普通的 JS 代码中:const { color } = useContext(ColorContext)return (<div>useContext 获取到的 color 值:{ color }{/* 在 JSX 中: */}<ColorContext.Consumer>{color => <span>共享的数据为:{color}</span>}</ColorContext.Consumer></div>)
}

useState-useRef

useRef-用法

  • 参数:在获取 DOM 时,一般都设置为 null(获取 DOM 对象时,如果拿不到 DOM 对象,此时,获取到的值就是 null)

  • 返回值:包含 current 属性的对象。

  • 注意:只要在 React 中进行 DOM 操作,都可以通过 useRef Hook 来获取 DOM(比如,获取 DOM 的宽高等)

  • 注意:useRef不仅仅可以用于操作DOM,还可以操作组件

import { useRef } from 'react'const App = () => {// 1 使用useRef能够创建一个ref对象const inputRef = useRef(null)const add = () => {// 3 通过 inputRef.current 来访问对应的 DOMconsole.log(inputRef.current.value)inputRef.current.focus()}return (<section className="todoapp">{/* 2 将 ref 对象设置为 input 的 ref 属性值。目的:将 ref 对象关联到 input 对应的 DOM 对象上 */}<input type="text" placeholder="请输入内容" ref={inputRef} /><button onClick={add}>添加</button></section>)
}export default App

Redux基本介绍------------------------

作用:集中式存储和管理应用的状态、处理组件通讯问题时,无视组件之间的层级关系、简化大型复杂应用中组件之间的通讯问题、数据流清晰,易于定位 Bug

Redux核心概念

为了让代码各部分职责清晰、明确,Redux 代码被分为三个核心概念:action/reducer/store

action(动作)

  • 描述要做的事情,特点:只描述做什么

  • 是一个js对象必须带有type属性,用于区分动作的类型

  • 根据功能的不同,可以携带额外的payload有效的载荷参数数据来完成相应功能

  • 例如 计数器功能描述
    { type: 'increment', payload: 10 } // +10
    { type: 'decrement', payload: 10 } // -10
  •  为了使action功能 多元并且灵活化,需要使用 action creator 函数去创建action,目的:简化多次使用 action 时,重复创建 action 对象,函数返回值依然是个action对象。
  • const decrement = payload => ({ type: 'decrement', payload })

reducer(函数)

  • 用来处理 action 并更新状态,是 Redux 状态更新的地方
  • 函数签名为:(prevState, action) => newState

  • 接收上一次的状态和 action 作为参数,根据 action 的类型,执行不同操作,最终返回新的状态,注意:该函数一定要有返回值,即使状态没有改变也要返回上一次的状态

  • 约定:reducer 是一个纯函数(相同的输入总是得到相同的输出),并且不能包含 side effect 副作用(比如,不能修改函数参数、不能修改函数外部数据、不能进行异步操作等)

  • 对于 reducer 来说,为了保证 reducer 是一个纯函数,不要:

    1. 不要直接修改参数 state 的值(也就是:不要直接修改当前状态,而是根据当前状态值创建新的状态值)

    2. 不要使用 Math.random() / new Date() / Date.now() / ajax 请求等不纯的操作

    3. 不要让 reducer 执行副作用(side effect)

  • // 示例:
    // state 上一次的状态
    // action 当前要执行的动作
    const reducer = (state=10, action) => {switch (action.type) {// 计数器增加case 'increment':// 返回新状态// return state + 1// 根据 action 中提供的 payload 来决定到底增加多少return state + action.payload// 注意:一定要有 default,如果将来 reducer 无法处理某个 action,就直接将上一次的状态返回即可default:return state}
    }

store(仓库)

  • 整合 action 和 reducer,一个应用只有一个 store

  • 维护应用的状态,获取状态:store.getState()

  • 发起状态更新时,需要分发 action:store.dispatch(action)

  • 创建 store 时接收 reducer 作为参数const store = createStore(reducer)

  • 订阅(监听)状态变化:const unSubscribe = store.subscribe(() => {})

  • 取消订阅状态变化: unSubscribe()

核心代码

import {createStore} from 'redux'// 创建 store
// 参数为:reducer 函数
const store = createStore(reducer)// 更新状态
// dispatch 派遣,派出。表示:分发一个 action,也就是发起状态更新
store.dispatch(action)
store.dispatch( increment(2) )// 获取状态
const state = store.getState()// 其他 API------
// 监听状态变化
const unSubscribe = store.subscribe(() => {// 状态改变时,执行相应操作// 比如,记录 redux 状态console.log(store.getState())
})// 取消监听状态变化
unSubscribe()

Redux获取状态默认值执行过程

  • 只要创建 store,给createStore(传递了 reducer),那么,Redux 就会调用一次 reducer
  • Redux 内部第一次调用 reducer: reducer的默认传值的type和payload为     (undefined, {type: "@@redux/INITv.a.4.t.t.p"})
  • 因为传入的状态值是 undefined ,并且是一个随机的 action type,因为是一个随机的 action type,所以,reducer 中 switch 一定无法处理该 action,那就一定会走 default。也就是直接返回了状态的默认值:10
  • Redux 内部拿到状态值store.getState()(比如,此处的 10)以后,就用这个状态值,来作为了 store 中状态的默认值

Redux代码执行流程

  1. 创建 store 时,Redux 就会先调用一次 reducer,来获取到默认状态(10)

  2. 然后分发动作 store.dispatch(action)更新状态

  3. 只要调用了dispatch操作,Redux store 内部就会调用 reducer 传入:上一次的状态(当前示例中就是:10)和当前传入的 action({ type: 'increment' }),计算出新的状态并返回

  4. reducer 执行完毕后,将最新的状态交给 store,store 用最新的状态替换旧状态,状态更新完毕

import { createStore } from 'redux'
const store = createStore(reducer)// reducer(10, { type: 'increment' })
function reducer(state = 10, action) {console.log('reducer:', state, action)switch (action.type) {case 'increment':return state + 1default:return state}
}console.log('状态值为:', store.getState()) // 10// 发起更新状态:
// 参数: action 对象
store.dispatch({ type: 'increment' })
// 相当于: reducer(10, { type: 'increment' })console.log('更新后:', store.getState()) // 11

React-Redux介绍

react-redux 库是 Redux 官方提供的 React 绑定库,为 React 接入 Redux,实现在 React 中使用 Redux 进行状态管理。 React 和 Redux 是两个独立的库,两者之间职责独立。因此,为了实现在 React 中使用 Redux 进行状态管理 ,就需要一种机制,将这两个独立的库关联在一起。这时候就用到 React-Redux 这个绑定库了。

react-redux 文档

react-redux 的使用分为两大步:

1 全局配置(只需要配置一次)

  1. 安装 react-redux:  yarn add react-redux  

  2. 从 react-redux 中导入 Provider 组件

  3. 导入创建好的 redux 仓库

  4. 使用 Provider 包裹整个应用

  5. 将导入的 store 设置为 Provider 的 store 属性值

index.js// 导入 Provider 组件
import { Provider } from 'react-redux'
// 导入创建好的 store
import store from './store'ReactDOM.render(<Provider store={store}><App /></Provider>,document.querySelector('#root')
)

2 组件接入(获取状态或修改状态)

获取状态:useSelector hook

  • useSelector:获取 Redux 提供的状态数据

  • 参数:selector 函数,用于从 Redux 状态中筛选出需要的状态数据并返回

  • 返回值:筛选出的状态

import { useSelector } from 'react-redux'const App = () => {const count = useSelector(state => state)return (<div><h1>计数器:{count}</h1><button>数值增加</button><button>数值减少</button></div>)
}

修改状态:useDispatch hook

  • useDispatch:拿到 dispatch 函数,分发 action,修改 redux 中的状态数据

import { useDispatch } from 'react-redux'const App = () => {const dispatch = useDispatch()return (<div><h1>计数器:{count}</h1>{/* 调用 dispatch 分发 action */}<button onClick={() => dispatch(increment(2))}>数值增加</button><button onClick={() => dispatch(decrement(5))}>数值减少</button></div>)
}

总结

  • 任何一个组件都可以直接接入 Redux,也就是可以直接:1 修改 Redux 状态 2 接收 Redux 状态

  • 并且,只要 Redux 中的状态改变了,所有接收该状态的组件都会收到通知,也就是可以获取到最新的 Redux 状态

  • 这样的话,两个组件不管隔得多远,都可以直接通讯了  

redux数据流动过程:

Redux应用

代码结构

 /store        --- 在 src 目录中创建,用于存放 Redux 相关的代码
   /actions    --- 存放所有的 action
   /reducers   --- 存放所有的 reducer
   index.js    --- redux 的入口文件,用来创建 store

Redux应用

ActionType

  • Action Type 指的是:action 对象中 type 属性的值

  • Redux 项目中会多次使用 action type,比如,action 对象、reducer 函数、dispatch(action) 等

  • 目标:集中处理 action type,保持项目中 action type 的一致性

  • action type 的值采用:'domain/action'(功能/动作)形式,进行分类处理,比如,

    • 计数器:'counter/increment' 表示 Counter 功能中的 increment 动作

    • 登录:'login/getCode' 表示登录获取验证码的动作

    • 个人资料:'profile/get' 表示获取个人资料

步骤

  1. 在 store 目录中创建 actionTypes 目录或者 constants 目录,集中处理

  2. 创建常量来存储 action type,并导出

  3. 将项目中用到 action type 的地方替换为这些常量,从而保持项目中 action type 的一致性

// actionTypes 或 constants 目录:const increment = 'counter/increment'
const decrement = 'counter/decrement'export { increment, decrement }// --// 使用:// actions/index.js
import * as types from '../acitonTypes'
const increment = payload => ({ type: types.increment, payload })
const decrement = payload => ({ type: types.decrement, payload })// reducers/index.js
import * as types from '../acitonTypes'
const reducer = (state, action) => {switch (action.type) {case types.increment:return state + 1case types.decrement:return state - action.payloaddefault:return state}
}
  • 注:额外添加 Action Type 会让项目结构变复杂,此操作可省略 ( 大型项目推荐使用 ) 。但,domain/action 命名方式强烈推荐!

Redux应用

Reducer的分离与合并

  • 随着项目功能变得越来越复杂,推荐 使用多个 reducer:按照项目功能划分,每个功能使用一个 reducer 来处理该功能的状态更新
  • 项目中会有多个 reducer,但是 store 只能接收一个 reducer,因此,需要将多个 reducer 合并为一根 reducer,才能传递给 store
  • 合并方式:使用 Redux 中的 combineReducers 函数

  • 注意:合并后,Redux 的状态会变为一个对象,对象的结构与 combineReducers 函数的参数结构相同

    • 比如,此时 Redux 状态为:{ a: aReducer 处理的状态, b: bReducer 处理的状态 }

  •  整个 Redux 应用的状态变为了对象,但是,对于每个 reducer 来说,每个 reducer 只负责整个状态中的某一个值,每个reducer只负责自己要处理的状态

  • 合并 reducer 后,redux 处理方式:只要合并了 reducer,不管分发什么 action,所有的 reducer 都会执行一次。各个 reducer 在执行的时候,能处理这个 action 就处理,处理不了就直接返回上一次的状态。所以,我们分发的某一个 action 就只能被某一个 reducer 来处理,也就是最终只会修改这个 reducer 要处理的状态,最终的表现就是:分发了 action,只修改了 redux 中这个 action 对应的状态!

import { combineReducers } from 'redux'// 计数器案例,状态默认值为:0
const aReducer = (state = 0, action) => {}
// Todos 案例,状态默认值为:[]
const bReducer = (state = [], action) => {}// 合并多个 reducer 为一个 根reducer
const rootReducer = combineReducers({aReducer: aReducer,bReducer: bReducer
})// 创建 store 时,传入 根reducer
const store = createStore(rootReducer)// 此时,合并后的 redux 状态: { a: 0, b: [] }reducer状态合并后,再次访问每个状态的时候,这个状态就是合并后的对象了,需要.上对象访问状态
import { useSelector } from 'react-redux'const App = () => {const count = useSelector(state => state.aReducer)const list = useSelector(state => state.bReducer)
}

注释:(个人针对redux的理解叙述)

  • const increment= payload => ({ type: 'increment', payload })
  • redux作为一个状态管理工具,将数据的状态分为了三部分,action、reducers和store
  • action作为一个描述数据用途的对象, { type: 'increment', payload: 10 },这里可以将这个用途对象理解为一个标志,increment就是计数器增加的标志,表示将来需要增加的标识
  • 当我们进行点击行为增加数据的时候,会调用store就会调用这个增加的标识store.dispacth(increment())
  • store.dispatch发起状态更新后,只要调用了dispatch操作,Redux store 内部就会调用 reducer 并且传入上一次的状态和当前传入的 action标识,相当于会给reduce分发一个状态标志"increment",从而使用switch函数进行标识的配对,分发正确的逻辑内容,计算出新的状态并返回
  • reducer 执行完毕后,将最新的状态交给 store,store 用最新的状态替换旧状态,状态更新完

注:

redux在这里 createStore 的使用已经过时,想要了解数据分发传递的实验过程可以参考上面,新的用法逻辑提现在新的文章中...

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

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

相关文章

分类预测 | MATLAB实现WOA-CNN-BiGRU鲸鱼算法优化卷积双向门控循环单元数据分类预测

分类预测 | MATLAB实现WOA-CNN-BiGRU鲸鱼算法优化卷积双向门控循环单元数据分类预测 目录 分类预测 | MATLAB实现WOA-CNN-BiGRU鲸鱼算法优化卷积双向门控循环单元数据分类预测分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.Matlab实现WOA-CNN-BiGRU多特征分类…

PyQt5安装以及使用

PyQt5安装以及使用 1 简介2 安装方法2.1 pip install PyQt52.2 pip install PyQt5‑5.15.9‑cp37‑cp37m‑win_amd64.whl 3 Qt相关工具介绍4 安装PyQt5-tools5 设置环境变量6 测试7 Qt Designer7.1 安装7.2 在 PyCharm 中配置 Qt Designer7.3 在PyCharm中测试Qt Designer 8 将u…

使用ExcelJS快速处理Node.js爬虫数据

什么是ExcelJS ExcelJS是一个用于处理Excel文件的JavaScript库。它可以让你使用JavaScript创建、读取和修改Excel文件。 以下是ExcelJS的一些主要特点&#xff1a; 支持xlsx、xlsm、xlsb、xls格式的Excel文件。可以创建和修改工作表、单元格、行和列。可以设置单元格样式、字…

android studio安卓模拟器高德SDK定位网络连接异常

背景 使用了高德SDK创建了一个 project, 下面是运行界面: 点击 "开始定位"按钮, 结果并没有返回定位信息, 而是报错了: 根据错误提示打开这个网址: https://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode, 并且找到错误码 4 的信息, 显示的是网…

【2023年11月第四版教材】第12章《质量管理》(第三部分)

第12章《质量管理》&#xff08;第三部分&#xff09; 5 管理质量5.1 管理质量★★★ &#xff08;17下9&#xff09;5.2 数据分析★★★5.3 数据表现★★★5.4 审计★★★ 6 控制质量6.1 控制质量6.2 数据收集★★★6.3 数据分析 ★★★6.4 数据表现★★★ 5 管理质量 组过程…

mianshiyan资料汇总(整理后)

前端优化方式 css3特性, [html5的特性](https://blog.csdn.net/qq_53472371/article/details/121881111) flex, 移动端开发, 各种居中 反爬虫&#xff0c;加密&#xff0c;前端攻击&#xff0c;跨域 cookie session jwt相关 前端优化方式 Turbopack WebComponentes6的新特性 B…

Python Opencv实践 - SIFT关键点检测

参考资料&#xff1a; 关键点检测SIFT算法笔记_亦枫Leonlew的博客-CSDN博客 SIFT特征检测算子和sift cv2.xfeatures2d.SIFT_create出错的解决办法_self.siftcv2.xfeatures2d.sift_create()_刘凯数据分析的博客-CSDN博客 import cv2 as cv import numpy as np import matplo…

Scrapy爬虫框架实战

Python实现爬虫是很容易的&#xff0c;一般来说就是获取目标网站的页面&#xff0c;对目标页面的分析、解析、识别&#xff0c;提取有用的信息&#xff0c;然后该入库的入库&#xff0c;该下载的下载。以前写过一篇文章《Python爬虫获取电子书资源实战》&#xff0c;以一个电子…

【VS插件】VS code上的Remote - SSH

【VS插件】VS code上的Remote - SSH 目录 【VS插件】VS code上的Remote - SSH获得Linux服务器或者Linux系统的IP地址下载插件远程登录注意如果Linux虚拟机系统无法连接成功可能是没有开启ssh服务优势 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.9.12 前言&#xff1…

c#动态保留小数位数的数值格式化方法实例----从小数点后非零数字保留两位进行四舍五入

c#动态保留小数位数的数值格式化方法实例----从小数点后非零数字保留两位进行四舍五入 功能介绍代码案例输出结果封装扩展方法控制台调用 其他方法地址 功能介绍 1. 输入的数字是整数&#xff0c;则直接返回整数部分的字符串表示。 2. 如果输入的数字是小数&#xff0c;则执行…

antd react 文件上传只允许上传一个文件且上传后隐藏上传按钮

antd react 文件上传只允许上传一个文件且上传后隐藏上传按钮 效果图代码解析 效果图 代码解析 import { Form, Upload, message } from antd; import { PlusOutlined } from ant-design/icons; import { useState, useEffect } from react; import { BASE_URL } from /utils/…

计算机视觉实战项目(图像分类+目标检测+目标跟踪+姿态识别+车道线识别+车牌识别)

图像分类 教程博客_传送门链接:链接 在本教程中&#xff0c;您将学习如何使用迁移学习训练卷积神经网络以进行图像分类。您可以在 cs231n 上阅读有关迁移学习的更多信息。 本文主要目的是教会你如何自己搭建分类模型&#xff0c;耐心看完&#xff0c;相信会有很大收获。废话不…