一:受控表单绑定
通过react状态去控制Input框的状态
监听输入框内容变化,每当用户输入时,e.target.value(输入框的值)会更新 value,从而实现输入框内容与状态同步。
import {useState} from "react"
// 1.准备一个React状态值
const [value,setValue] = useState("")
// 2.通过value属性绑定状态,通过onChange属性绑定状态同步的函数
// 通过事件参数e拿到输入框的最新的值,反向修改到react状态身上
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
二:react中获取dom(使用useRef)
使用useRef获取input输入框的DOM对象
①1.useRef生成ref对象,并与JSX绑定
②2.dom可用时,通过inputRef.current拿到dom对象
import {useRef} from "react";
function App(){
// 1. 创建一个 ref 对象,并初始化为 null
const inputRef = useRef(null)
// 2. 定义一个函数,点击按钮时获取 input 的 DOM 对象
const showDom =()=>{
console.log(inputRef.current) // 输出 input 的 DOM 对象
}
return(
<div>
{/* 3. 绑定 ref 到 input 元素 */}
<input type="text" ref={inputRef} />
{/* 4. 点击按钮时执行 showDom 函数 */}
<button onClick={showDom}>获取dom</button>
</div>
)
}
三:案例-发表评论
1.核心功能实现
①用数控绑定方式,可以把用户输入的东西,收集到content里面
②点击时发布评论,替换content字段,收集到的数据是什么就绑定什么
③延续数据修改不可变的方式,原本的所有数据都展开,增加一条自己的数据
※需求:获取评论内容,点击发布按钮发布评论
⭐setCommentList([...commentList, newComment]):
...commentList 复制已有的评论列表。
{...} 创建一个新评论对象,并添加到列表中。
setCommentList() 更新 commentList 状态,让页面重新渲染,显示新评论。
// 发表评论
const [content,setContent] = useState("")
const handPublish =()=>{
setCommentList([
...commentList,
{
rpid:100,
user:{
uid:"30009257",
avatar,
uname:"黑马前端",
},
content:content,
ctime:"10-19 09:00",
like:66,
}
])
}
// 评论框
<textarea
className="reply-box-textarea"
placeholder="发一条友善的评论"
value={content}
onChange={(e)=>setContent(e.target.value)}
/>
// 发布按钮
<div className="reply-box-send">
<div className="send-text" onClick={handPublish}>发布</div>
</div>
2.id和时间处理
需求:rpid要求一个唯一的随机数id(uuid)
ctime要求以当前时间为标准,生成固定格式(dayjs)
// 安装uuid
npm install uuid
// 使用方式
import {v4 as uuidv4} from "uuid";
uuidv4();
// 安装Day.js
npm install dayjs
// 使用方式
import dayjs from "dayjs"
Format
{
import {v4 as uuidV4} from "uuid"
import dayjs from "dayjs"
rpid:uuidV4(), //随机id
user:{
uid:"30009257",
avatar,
uname:"黑马前端",
},
content:content,
ctime:dayjs(new Date()).format("MM-DD hh:mm"),// 格式化 月-日 时:分
like:66,
}
3.清空内容和聚焦实现
需求:清空内容-把控制input框的value状态设置为空串
重新聚焦-拿到input的dom元素,调用focus方法
inputRef.current.focus() 让输入框自动获取焦点
// 1.清空输入框内容
setContent("")
// 2.重新聚焦 dom(useRef) -focus
const inputRef = useRef(null)
inputRef.current.focus()
// 评论框
<textarea
className="reply-box-textarea"
placeholder="发一条友善的评论"
ref={inputRef}
value={content}
onChange={(e)=>setContent(e.target.value)}
/>
四:父子组件通信
组件之间的数据传递
1.父传子基础实现
步骤:①父组件传递数据-在子组件标签上绑定属性
②子组件接收数据-子组件通过props参数接收数据
props:包含着父组件传递过来的所有数据
父组件App通过props向子组件Son传递数据,然后子组件Son在渲染时接收并显示这个数据。
function Son(props){
console.log(props)
return <div> this is son,{props.name}</div>
}
function App(){
const name = "this is app name"
return(
<div>
<Son name = {name}/> {/* 传递name变量给Son组件 */}
</div>
)
}
2.props说明
可以传递任意的数据:数字,字符串,布尔值,数组,对象,函数,jsx
props是只读对象,子组件只能读取props中的数据,不能直接进行修改,父组件的数据只能有父组件修改
3.父传子children说明
父组件通过children传递子元素给Son组件,然后Son组件可以通过 props.children渲染这个子元素。
props.children:Son组件的子元素
function Son(props){
console.log(props)
// props.children在这里是<span> this is span </span>
return <div> this is son,{props.children}</div>
}
function App(){
return(
<div>
<Son>
<span> this is span</span>
</Son>
</div>
)
}
4.子传父实现
在子组件中调用父组件中的函数并传递实参
父组件通过props传递一个函数getMsg给子组件,然后子组件在点击按钮时调用这个函数,并把自己的数据sonMsg传回给父组件。
function Son({onGetSonMsg}){
// Son组件中的数据
const sonMsg = "this is son msg"
return(
<div>
this is Son
<button onClick ={()=>onGetSonMsg(sonMsg)}>sendMsg</button>
</div>
)
}
function App(){
const [msg,setMsg] = useState("")
const getMsg = (msg)=>{
console.log(msg)
setMsg(msg)
}
return(
<div>
this is App,{msg}
<Son onGetSonMsg = {getMsg}/>
</div>
)
}
五:useEffect
1.概念理解和基础使用
用来执行一些“自动触发的操作”,而不是等到用户点击按钮、输入内容等事件才执行。可以想象成一个“自动运行的代码块”:当组件加载(渲染)时,就会自动执useEffect里的代码,当某些数据变化时(比如 state 发生变化),useEffect也可以自动执行。
useEffect 不需要用户手动触发(比如点击按钮),它会在页面加载或状态变化时自动执行。比如:页面一打开就执行代码,或某个状态变化后自动执行代码
你只管写在useEffect里,React会帮你找合适的时机自动执行!
useEffect(() =>{},[])
// 参数1是一个函数,在函数内部可以放置要执行的操作
// 参数2是一个数组,在数组里放置依赖项,不同依赖项会影响第一个参数函数的执行,
// 当是一个空数组的时候,只会在组件组件首次渲染时执行一次
⭐作用
①首次进入页面后,初始化操作
②监视某个值的变化
③退出页面后,执行收尾操作
2.不同依赖项说明
①空数组依赖:只在初始渲染时执行一次
import { useEffect, useState } from "react";
function App() {
// 2.传入空数组依赖 初始执行一次
useEffect(()=>{
console.log("副作用函数执行了")
},[])
return (
<div>
this is App
<button onClick ={()=>setCount(count +1)}>+{count}</button>
</div>
)
}
export default App;
②添加特定依赖项:组件初始渲染+特性依赖项变化时执行
import { useEffect, useState } from "react";
function App() {
const [count,setCount] = useState(0)
// 3.传入特定依赖项 初始 + 依赖项变化时执行
useEffect(()=>{
console.log("副作用函数执行了")
},[count])
return (
<div>
this is App
<button onClick ={()=>setCount(count +1)}>+{count}</button>
</div>
)
}
export default App;
3.清除副作用
在useEffect里,“副作用”指的是组件渲染时需要执行的额外操作,比如:
发送网络请求,操作 DOM,订阅事件,定时器。这些操作不是组件渲染UI所必需的,但又是程序运行时需要的,所以叫“副作用”。
React提供了清理副作用的方法,就是在useEffect里返回一个函数,这个函数会在组件卸载或useEffect重新执行时运行,负责清除不需要的副作用。
useEffect是“开灯”,但如果灯一直亮着没人关,就会浪费电。所以React允许你在组件卸载时“关灯”,就是清除副作用!
useEffect(() =>{
// 实现副作用操作逻辑
return()=>{
// 清除副作用逻辑
}
},[])
在Son组件渲染时开启一个定时器,卸载时清除这个定时器
①Son 组件在渲染时启动一个定时器,每隔 1 秒输出 "定时器执行中"。
②App 组件包含一个 show 状态,控制 Son 组件是否显示。
③点击按钮 setShow(false) 会卸载 Son 组件,同时 useEffect 清理定时器,防止定时器继续运行。
import { useEffect, useState } from "react";
function Son(){
// 1.渲染时开启一个定时器
useEffect(()=>{
const timer = setInterval(()=>{
console.log("定时器执行中")
},1000)
return () =>{
// 清除副作用 组件卸载时
clearInterval(timer)
}
},[])
return <div>this is son</div>
}
function App() {
// 通过条件渲染模拟组件卸载
const [show,setShow] = useState(true)
return (
<div>
{show && <Son />}
<button onClick ={()=>setShow(false)}>卸载Son组件</button>
</div>
)
}
export default App;
六:自定义hook实现
useToggle是一个自定义Hook,用于管理 true/false 状态。
好处是让toggle逻辑可以复用,多个组件可以直接使用。
按钮点击时,toggle() 切换 value,从而控制
import { useEffect, useState } from "react";
// 封装自定义hook
// 1.声明一个以use打头的函数
// 2.在函数体内封装可复用的逻辑 只要是可复用的逻辑
// 3.把组件中用到的状态或者回调return出去 以对象或者数组
// 4.在哪个组件中要用到这个逻辑,就执行这个函数,解构出来状态和回调进行使用
function useToggle(){
// 可复用的逻辑代码
const [value,setValue] = useState(true)
const toggle = ()=>setValue(!value)
// 哪些状态和回调函数需要在其他组件中使用 return
return{
value,
toggle
}
}
function App() {
const {value, toggle} = useToggle()
return (
<div>
{value && <div>this is div</div>}
<button onClick ={toggle}>toggle</button>
</div>
)
}
export default App;
七:reacthooks使用规则说明
1.只能在组件中或者其他自定义hook函数中调用
2.只能在组件的顶层调用,不能嵌套在if for其他函数中