Ref从入门到入土

news/2025/2/13 17:39:29/

首先做个对比:

 功能一:引用一个值做持久化记忆

场景:清除定时器

import { useRef } from "react"
import { useState } from "react"
// ref:1.引用一个值 做持久化记忆 
// let num = useRef(1)
// console.log(num.current++);
// 避免渲染ref的值,其值改变时不会触发更新(区别于state)
const App = () => {const [count, setCount] = useState(0)// let timer = null// const handleClick = () => {//     setCount(count + 1)//     // 不能有效清除定时器,因为每次只能清除当前作用域的timer,但是每次setState都会产生新的作用域,则多次点击会导致定时器累加//     clearInterval(timer)//     timer = setInterval(() => {//         console.log('setInterval...');//     }, 1000);// }let timer = useRef(null)const handleClick = () => {setCount(count + 1)// ref具有记忆性,可以拿到第一次产生的timer,然后清除,保证每次只有一个定时器在clearInterval(timer.current)timer.current = setInterval(() => {console.log('setInterval...');}, 1000);}return (<>hello hook<button onClick={handleClick}>按钮</button><br />count:{count},</>)
}export default App

 功能二:在react中操作dom(避免原生写法

const App = () => {const myRef = useRef(null)const fun = () => {console.log(myRef.current.innerHTML);myRef.current.style.color = 'skyblue'}const list = [{ id: 1, text: 'aaa' },{ id: 2, text: 'bbb' },{ id: 3, text: 'ccc' }]return (<><button onClick={fun}>点击让div变色</button><div ref={myRef}>div</div>{/* 循环中操作ref可以使用回调写法 */}<ul>{list.map((item) => {return <li key={item.id} ref={(mf) => { mf.style.background = 'pink' }}>{item.text}</li>})}</ul></>)
}export default App 

注意:当给子组件添加ref时,需要对其 forwardRef 转发,用于向父组件公开其dom


const Zi = forwardRef(function myInput(props, refs) {return <input type="text" ref={refs} />
})const App = () => {const myref = useRef(null)const fn = () => {myref.current.focus()myref.current.style.background = 'skyblue'}return (<>hello App<button onClick={fn}>点击变色</button><Zi ref={myref} /></>)}export default App

进阶:useImperativeHandle用于为组件自定义暴露方法

import { useRef, forwardRef, useImperativeHandle } from "react"const Zi = forwardRef(function myInput(props, refs) {const inputRef = useRef(null)useImperativeHandle(refs, () => {return {myFocus() {inputRef.current.focus()},focusAndStyle() {inputRef.current.focus()inputRef.current.style.background = 'red'}}})return (<input type="text" ref={inputRef} />)
})
const App = () => {const myref = useRef(null)const fn = () => {myref.current.myFocus()myref.current.focusAndStyle()// 以下会报错 myref.current.focus is not a function,因为只有以上俩方法暴露了// myref.current.focus()  }return (<>hello App<button onClick={fn}>点击</button><Zi ref={myref} /></>)}export default App


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

相关文章

科兴未来|2023“数智未来,聚放神采”医疗科技创新挑战赛

一、赛事亮点 聚焦前沿神经科学与脑科学领域 展示优质创新产品、技术、平台与服务 汇聚学术端、产业端、投资端多维专业视角 搭建合作交流、产业赋能与生态融合平台 共话行业发展方向与动态趋势 二、赛事简介 2023医疗科技创新挑战赛聚焦于神经科学及脑科学领域的前沿技…

matlab使用教程(10)—脚本和函数

1.概述 MATLAB 提供了一个强大的编程语言和交互式计算环境。您可以使用此语言在 MATLAB 命令行中一次输入一个命令&#xff0c;也可以向某个文件写入一系列命令&#xff0c;按照执行任何 MATLAB 函数的相同方式来执行这些命令。使用 MATLAB 编辑器或任何其他文件编辑器可以创建…

从浏览器输入url到页面加载(七)服务端机器一般部署在哪里

前言 上一节&#xff0c;我们说到了CDN和路由器的关系&#xff0c;说到了公有地址&#xff0c;说到了通信线路服务&#xff0c;这一节跳过那些看不懂的深层知识&#xff0c;直接开始说web服务器。 1. 服务端机器为什么不部署在公司内部 记得在之前的一段时间里&#xff0c;公…

24届近5年重庆邮电大学自动化考研院校分析

今天给大家带来的是重庆邮电大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、重庆邮电大学 学校简介 重庆邮电大学简称"重邮"&#xff0c;坐落于直辖市-重庆市&#xff0c;入选国家"中西部高校基础能力建设工程”、国家“卓越工程师教育培养计划…

ElementPlus文件上传 ,在上传前钩子中判断文件是否为图片

在ElementPlus中&#xff0c;可以使用beforeUpload属性来指定上传文件之前的钩子函数&#xff0c;在该函数中可以对文件进行判断并进行相关操作。 首先&#xff0c;在data中定义一个isImage变量来记录文件是否为图片&#xff0c;初始值为false。然后&#xff0c;在钩子函数中判…

一百四十七、Kettle——Linux上安装的kettle8.2连接ClickHouse数据库

一、目标 kettle8.2在Linux安装好后&#xff0c;需要与ClickHouse数据库建立连接 二、前提准备 1、在Linux已经安装好kettle并可以启动kettle 2、kettle版本是8.2 3、已知Linux系统架构是64位 4、准备好ClickHouse的驱动包(借他人网盘链接一用) https://pan.baidu.com/s/…

Winform 打开文件夹、文件、拖拽上传

参考原文&#xff1a;https://blog.csdn.net/u012543266/article/details/21834073 1、打开文件 private void button1_Click(object sender, EventArgs e){OpenFileDialog dialog new OpenFileDialog();dialog.Multiselect true;//该值确定是否可以选择多个文件dialog.Titl…

ElasticSearch索引生命周期管理--DELETE

概要 ElasticSearch中的索引生命周期管理&#xff0c;也就是ilm&#xff08;Manage the index lifecycle&#xff09;,是指定了索引在不同周期下的处理策略。ilm 的对象是索引而不是索引中的数据。ilm 包括四个阶段&#xff1a;hot 、warm、cold和delete。hot、warm和cold表示…