useChange
1 .绑定表单,创建一个存储变量的数据仓库,暴露出一这个属性和操作这个属性的方法,让别的实例使用
2 .方便维护多个表单
import React,{useState,useCallback}from 'react'
export default function useChange(initValue){
const [value,setValue]=useState(initValue)
const onChange=useCallback(e=>setValue(e.target.value),[])
return {
value,
setValue,
onChange,
bindEvent:{
onChange,
value,
},
bind:{
onChange:setValue,
value,
}
}
}
2 .使用
const useName=useChange('飞机')
const usePassword=useChange('')
return (
<>
<input type="text" {...useName.bindEvent}/>
<input type="password" {...usePassword.bindEvent}/>
<span>name</span>{useName.value}|<span>password</span>{usePassword.value}
</>
)
useBind
import {useMemo} from 'react'
// 对传入的函数进行useMemo包装,使他具有缓存属性
export default function useBind(fn,args){
return useMemo(()=>{
fn&&fn.bind(null,...args)
},args)
}
function Demo(props) {
const {id, onClick} = props
const handleClick = useBind(onClick, id)
return <ComplexComponent onClick={handleClick}></ComplexComponent>
}
useActive
// 检测目标是否鼠标按下,鼠标按下的时候显示true,鼠标释放的时候恢复为false
// 并不是鼠标抚摸的时候触发
import {useEffect,useState}from 'react'
export default function useActive(refEl){
const [value,setValue]=useState(false)
useEffect(()=>{
const handleMouseDown=()=>{
setValue(true)
}
const handleMouseUp=()=>{
setValue(false)
}
if(refEl&&refEl.current){
refEl.current.addEventListener('mousedown',handleMouseDown)
refEl.current.addEventListener('mouseup',handleMouseUp)
}
return ()=>{
if(refEl&&refEl.current){
refEl.current.removeEventListener('mousedown',handleMouseDown)
refEl.current.removeEventListener('mouseup',handleMouseUp)
}
}
},[])
return value
}
useTimeout
// 由用户触发,在指定时间之后恢复状态,可以用来节流,比如一段时间内只能执行1次函数,避免重复点击触发
import {useState,useRef, useCallback} from 'react'
export default function useTimeout(number,count){
// number:时间,1000毫秒内只能触发一次事件
// count:次数,规定时间内可以触发的次数,默认是1次
// 1000:2 :传入这样的参数意味着1秒内最多可以触发2次这个事件
const [ready,setReady]=useState(false)
const timerRef=useRef()
const countRef=useRef(1)
const start=useCallback(()=>{
clearTimeout(timerRef.current)
if(countRef.current>=count){
setReady(true)
}
countRef.current+=1
console.log(countRef.current)
timerRef.current=setTimeout(()=>{
setReady(false)
countRef.current=1
},number)
},[number])
const stop=useCallback(()=>{
clearTimeout(timerRef.current)
},[])
return [ready,start,stop]
}
const [disabled,start]=useTimeout(10000,2)
function handleClick(){
setNum(num+1)
start()
console.log('点击')
}
//当前是否能执行的标志是在disabled这个值
useKeybinds
// 监听组合键
import { useEffect,useRef,useState } from "react"
import useTimeout from './useTimeout'
export default function useKeyBindings(keyCodes,isOrder){
// keyCodes:数组,需要检测按下的键值的数组
// isOrder:是否完全顺序一致,比如顺序必须匹配,不能乱序,和给的数组必须完全匹配顺序
const [match,setMatch]=useState(false)
const keyCodeRef=useRef()
keyCodeRef.current=[]
// 一秒之内只能触发匹配数组次数对应的keydown事件
useEffect(()=>{
document.addEventListener('keydown',handleKeyDown)
document.addEventListener('keyup',handleKeyUp)
function handleKeyDown(e){
if(keyCodeRef.current.length<keyCodes.length){
if(!keyCodeRef.current.includes(e.key)){
keyCodeRef.current.push(e.key)
// 满足条件做一次检测
if(keyCodeRef.current.length==keyCodes.length){
if(isOrder){
// 全匹配
for(let i=0;i<keyCodes.length;i++){
if(keyCodeRef.current[i]!==keyCodes[i]){
setMatch(false)
break;
}
if(i==keyCodes.length-1){
setMatch(true)
}
}
}else{
for(let i=0;i<keyCodes.length;i++){
if(!keyCodes.includes(keyCodeRef.current[i])){
setMatch(false)
break;
}
if(i==keyCodes.length-1){
setMatch(true)
}
}
}
}
}
}else{
return
}
}
function handleKeyUp(e){
console.log(keyCodeRef.current)
setMatch(false)
//感觉打印还是有点问题啊。
keyCodeRef.current=[]
}
return ()=>{
document.removeEventListener('keydown',handleKeyDown)
document.removeEventListener('keyup',handleKeyUp)
}
})
return [match]
}
//1.我这个函数修改一个值,但是反过来我这个函数依赖这个值进行再次渲染,这样会不会造成死循环
//键值对应:由于使用的是event.key这个参数用来对比,所以
// ctrl:Control
react-use使用的是一个库,超级简单
初始化state只创建一次
function createState(props){
return props.count
}
function useCreateState(){
const [count,SetCount]=useState(()=>createState({count:10}))
// 这个count的定义使用了函数方法创建,createState函数只会被调用一次,首次渲染的时候,避免重新创建count
// 避免重新创建useRef的值
// 1.useRef是不能通过传入参数来实现这个效果,需要写独特的函数、、
const ref=useRef(null)
function getObserver(){
if(ref.current===null){
ref.current=createState({count:10})
}else{
return ref.current
}
}
}
传入参数的问题
function useCounter(){
const [count,setCount]=useState(0)
// useEffect(()=>{
// setInterval(() => {
// console.log('useCounter',count)
// setCount(count + 1);
// }, 1000);
// },[])
// 问题1:这里的count取的是初始执行这个useEffect时候的值,也就是0,所以每次加计算的都是从0开始,所以这里的值应该会一直是0
// useEffect(()=>{
// let id=setInterval(() => {
// console.log('useCounter',count)
// setCount(count + 1);
// }, 1000);
// },[count])
// 问题2:每次重新执行,setInterval都是会重新定义,所以需要一个全局变量来保存这个东西,比如用一个ref来保存,或者使用函数模式设置count
useEffect(()=>{
let id=setInterval(() => {
console.log('useCounter',count)
setCount(c=>c+1);
}, 1000);
// 不需要传入依赖,只执行一次,setInterval不会重置,setCount的函数设置方式,可以实现我们的效果
},[])
// 或者全局挂在一个ref上面
return [count]
}
网友评论