做课件好用的网站,传奇类网页游戏大全,网络管理系统界面,北京it培训机构哪家好一、useRef
useRef返回一个ref对象#xff0c;返回的ref对象再组件的整个生命周期保持不变。
最常用的ref是两种用法#xff1a;
用法一#xff1a;引入DOM#xff08;或者组件#xff0c;但是需要是class组件#xff09;元素#xff1b; 案例一#xff1a;引用DOM …一、useRef
useRef返回一个ref对象返回的ref对象再组件的整个生命周期保持不变。
最常用的ref是两种用法
用法一引入DOM或者组件但是需要是class组件元素 案例一引用DOM
import React, {useRef} from react;class TestCpn extends React.Component{render() {return h2TestCpn/h2}
}function TestCpn2(props) {return h2TestCpn2/h2
}export default function RefHookDemo01() {const titleRef useRef()const inputRef useRef()const testRef useRef()const testRef2 useRef()function changeDOM() {titleRef.current.innerHTML hello worldinputRef.current.focus()console.log(testRef.current)console.log(testRef2.current)}return (divh2 ref{titleRef}RefHookDemo01/h2input typetext ref{inputRef}/TestCpn ref{testRef} /TestCpn2 ref{testRef2} /button onClick{e changeDOM()}修改DOM/button/div)
}
用法二保存一个数据这个对象在整个生命周期中可以保存不变 案例二使用ref保存上一次的某一个值
import React, {useEffect, useRef, useState} from react;export default function RefHookDemo02() {const [count, setCount] useState(0)const numRef useRef(count)useEffect(() {numRef.current count}, [count])return (div{/*h2numRef中的值: {numRef.current}/h2*/}{/*h2count中的值: {count}/h2*/}h2count上一次的值{numRef.current}/h2h2count当前的值{count}/h2button onClick{e setCount(count 10)}10/button/div)
}
二、useImperativeHandle
useImperativeHandle并不是特别好理解我们一点点来学习。
我们先来回顾一下ref和forwardRef结合使用
通过forwardRef可以将ref转发到子组件子组件拿到父组件中创建的ref绑定到自己的某一个元素中
import React, {forwardRef, useRef} from react;const HYInput forwardRef((props,ref) {return input ref{ref} typetext/}
)export default function ForwardRefDemo() {const inputRef useRef()return (divHYInput ref{inputRef}/button onClick{e inputRef.current.focus()}聚焦/button/div)
}
forwardRef的做法本身没有什么问题但是我们是将子组件的DOM直接暴露给了父组件
直接暴露给父组件带来的问题是某些情况的不可控父组件可以拿到DOM后进行任意的操作但是事实上在上面的案例中我们只是希望父组件可以操作的focus其他并不希望它随意操作
通过useImperativeHandle可以只暴露固定的操作
通过useImperativeHandle的Hook将传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起所以在父组件中使用 inputRef.current时实际上使用的是返回的对象比如我调用了 focus函数
import React, {forwardRef, useImperativeHandle, useRef} from react;const HYInput forwardRef((props, ref) {const inputRef useRef()useImperativeHandle(ref, () {return {focus: () {inputRef.current.focus()console.log(useImperativeHandle中回调函数返回的对象里面的focus)}}}, [inputRef.current])return input ref{inputRef} typetext/}
)export default function ForwardRefDemo02() {const inputRef useRef()return (divHYInput ref{inputRef}/button onClick{e inputRef.current.focus()}聚焦/button/div)
}
三、useLayoutEffect
useLayoutEffect看起来和useEffect非常的相似事实上他们也只有一点区别而已
useEffect会在渲染的内容更新到DOM上后执行不会阻塞DOM的更新useLayoutEffect会在渲染的内容更新到DOM上之前执行会阻塞DOM的更新
如果我们希望在某些操作发生之后再更新DOM那么应该将这个操作放到useLayoutEffect。 案例 useEffect和useLayoutEffect的对比
四、自定义Hook
自定义Hook本质上只是一种函数代码逻辑的抽取严格意义上来说它本身并不算React的特性。
需求0所有的组件在创建和销毁时都进行打印
组件被创建打印 组件被创建了组件被销毁打印 组件被销毁了 import React, {useEffect} from react;
const Home (props) {useEffect(() {console.log(Home组件被创建出来了~)return () {console.log(Home组件被销毁了)}}, [])return h2Home/h2
}
const Profile (props) {useEffect(() {console.log(Profile组件被创建出来了~)return () {console.log(Profile组件被销毁了)}}, [])return h2Profile/h2
}
export default function CustomHookLifeDemo01() {useEffect(() {console.log(CustomHookLifeDemo01组件被创建出来了~)return () {console.log(CustomHookLifeDemo01组件被销毁了)}}, [])return (divh2CustomHookLifeDemo01/h2Home /Profile //div)
} import React, {useEffect} from react;
const Home (props) {useLoggingLife(Home)return h2Home/h2
}
const Profile (props) {useLoggingLife(Profile)return h2Profile/h2
}
export default function CustomHookLifeDemo01() {useLoggingLife(CustomHookLifeDemo01)return (divh2CustomHookLifeDemo01/h2Home /Profile //div)
}
function useLoggingLife(name) {useEffect(() {console.log(${name}组件被创建出来了~)return () {console.log(${name}组件被销毁了)}}, [])
}
需求一Context的共享 import {useContext} from react;
import {TokenContext, UserContext} from ../App;function useUserContext() {const user useContext(UserContext)const token useContext(TokenContext)return [user, token]
}export default useUserContext
需求二获取鼠标滚动位置 需求三localStorage数据存储