为了防止页面出错导致无限循环 必须要保证自己的errorElement是存在且不出错 因为出错就会访问errorElement 然后会一直循环
自制一个hooks/useSwipe是 写一个可以当用户手指移动另页面可以跳转的交互
思路就是
- 1.要将需要移动的元素进行关联用到的是在main上 利用 ref={main} 然后利用useRef给ref.current赋初值,(一开始将其赋为null,因为undefined会报错
注意这里的useRef返回一个可变的 ref 对象,该对象只有个 current 属性,初始值为传入到()里面 且直到挂载了后 ref.current才能获取这个元素的DOM值
但是由于useSpite第一个element不能为空 所以我们传的应该是ref这个对象 也就是main
<main shrink-1 grow-1 relative ref={main}>
</main>
const main = useRef<HTMLElment>(null)
const {direction} = useSwipe(main , {onTouchStart: e => e.preventDefault()}
- 2.然后就可以开始写我们的hooks 最后返回的是direction 我们要先写一个用户手指点到的部分与移动的部分的差值来判断怎么移动
import { RefObject, useEffect, useRef, useState } from "react";
interface Config {
onTouchStart?: (e: TouchEvent) => void
onTouchMove?: (e: TouchEvent) => void
onTouchEnd?: (e: TouchEvent) => void
}
//<> : 括起来的是语法说明 config在这里起到的作用 可以将e提出来到外面 进行e.preventDefault 去除默认操作 是去掉每次点击后闪白色页面的方法
//引入一个config是一个Config类型 Config作用就是可以将有config参数的元素里面的事件进行额外的操作
export const useSwipe = (elementRef: RefObject<HTMLElement>, config?: Config) => { //直接接受 main 即element的ref
const [direction , setDirection] =useState<''|'left'|'right'>('')
const x = useRef(-1)
const onTouchStart = (e: TouchEvent) => {
config?.onTouchStart?.(e)
x.current = e.touches[0].clientX //第一个手指按到的X坐标
}
const onTouchMove = (e: TouchEvent) => {
config?.onTouchStart?.(e)
const newX = e.touches[0].clientX
const d = newX - x.current
if (Math.abs(d) < 3) {
setDirection('')
} else if (d > 0) {
setDirection('right')
} else {
setDirection('left')
}
}
const onTouchEnd = (e: TouchEvent) => {
config?.onTouchStart?.(e)
setDirection('')//记得要在动画结束后将direction赋为空
}
useEffect(() => {//挂载后监听事件
if (!elementRef.current) { return }
elementRef.current.addEventListener('touchstart', onTouchStart)
elementRef.current.addEventListener('touchmove', onTouchMove)
elementRef.current.addEventListener('touchend', onTouchEnd)
return () => {
if (!elementRef.current) { return }
elementRef.current.removeEventListener('touchstart', onTouchStart)
elementRef.current.removeEventListener('touchmove', onTouchMove)
elementRef.current.removeEventListener('touchend', onTouchEnd)
}
}, [])
return { direction }
}