为什么要渲染两个div

问题描述 投票:0回答:1

当组件安装并设置为使用事件侦听器跟随鼠标时,我通过在 useEffect 挂钩中动态附加 div 元素来创建自定义光标。但是,正在渲染两个 div — 一个正确跟随鼠标,而另一个则停留在视口的左上角。

import { useRef, useEffect, useState } from "react"

function Pcanvas({width, height, pixelSize}){
    const [canvasColor, setCanvasColor] = useState("#dcdcdc")
    const [pencilSize, setPencilSize] = useState(pixelSize)
    const canvasRef = useRef(null)
    var mousePressed = false

    function mouseCursor(){
        const cursor = document.createElement("div")
        cursor.className = 'cursor'
        cursor.style.backgroundColor = 'black'
        cursor.style.width = pencilSize + 'px'
        cursor.style.height = pencilSize + 'px'
        cursor.style.position = 'absolute';
        cursor.style.display = 'block';
        cursor.style.zIndex = 999;
        cursor.style.pointerEvents = 'none';
        document.body.appendChild(cursor)
        
        console.log(cursor.getBoundingClientRect().y)
    }
    
    function handleMouseMov(event){
        const cursor = document.getElementsByClassName('cursor')[0]
        console.log(cursor.getBoundingClientRect().y)
        if(cursor){
            cursor.style.top = event.clientY-(pencilSize/2) + 'px'
            cursor.style.left = event.clientX-(pencilSize/2) + 'px'
        }
    }

    function handleMouseLeave(event){
        const cursor = document.getElementsByClassName('cursor')[0]
        if(cursor){
            cursor.style.display = 'none'
        }
    }
    
    function handleMouseEnter(event){
        const cursor = document.getElementsByClassName('cursor')[0]
        if(cursor){
            cursor.style.display = 'block'
        }
    }
    
    useEffect(() => {
        const canvas = canvasRef.current 
        mouseCursor()
        document.body.addEventListener('mouseenter', handleMouseEnter)
        document.body.addEventListener('mousemove', handleMouseMov)
        document.body.addEventListener('mouseleave', handleMouseLeave)

        return(() => {
            document.body.removeEventListener('mouseenter', handleMouseEnter)
            document.body.removeEventListener('mousemove', handleMouseMov)
            document.body.removeEventListener('mouseleave', handleMouseLeave)
        })
    }, [pencilSize])

    return(
        <></>
    )
}

export default Pcanvas

reactjs jsx
1个回答
1
投票

使用 React 时,您应该避免

createElement
,尤其是
getElementsByClassName

让组件自行渲染

div
,然后在需要时使用
useRef
更改任何样式。

const { useRef, useEffect, useState } = React;

function Pcanvas({ width, height, pixelSize = 15 }){

    const cursor = useRef(null)
    
    const [pencilSize, setPencilSize] = useState(pixelSize)
       
    const handleMouseEnter = (event) => cursor.current.style.display = 'block';
    const handleMouseLeave = (event) => cursor.current.style.display = 'none';
    const handleMouseMov = (event) => {
        cursor.current.style.top = event.clientY-(pencilSize/2) + 'px'
        cursor.current.style.left = event.clientX-(pencilSize/2) + 'px'
    }
    
    useEffect(() => {
        document.body.addEventListener('mouseenter', handleMouseEnter);
        document.body.addEventListener('mousemove', handleMouseMov);
        document.body.addEventListener('mouseleave', handleMouseLeave);
        return(() => {
            document.body.removeEventListener('mouseenter', handleMouseEnter);
            document.body.removeEventListener('mousemove', handleMouseMov);
            document.body.removeEventListener('mouseleave', handleMouseLeave);
        })
    }, [pencilSize])
    
    return (
        <div 
            ref={cursor} 
            className={'cursor'} 
            style={{ width: pencilSize, height: pencilSize, display: 'none' }}
        />
    );
}

ReactDOM.render(<Pcanvas />, document.getElementById("react"));
html, body, #react { height: 100%; }

.cursor {
  background: black;
  position: absolute;
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.