美文网首页
自定义hook-事件处理

自定义hook-事件处理

作者: skoll | 来源:发表于2020-07-08 19:43 被阅读0次

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]

}

相关文章

网友评论

      本文标题:自定义hook-事件处理

      本文链接:https://www.haomeiwen.com/subject/hokrfktx.html