首页 > 解决方案 > 使用事件引用删除事件侦听器

问题描述

我正在尝试让网页在 Q、W、E、R 和 T 的按键上播放鼓声音频。音频存储在 React 状态对象中:

    const [sounds, setSounds] = useState({
        loadState: false,
        Q : "",
        W : "",
        E : "", 
        R : "",
        T : ""
    })

并将更新为几个 const 之一,表示由稍后显示的按钮控制的不同样式:

    function makeAudioObj(genre) {
        return ({
            loadState: true,
            Q : new Audio(`/audio/${genre}/${genre}_kick.wav`),
            W : new Audio(`/audio/${genre}/${genre}_snare.wav`),
            E : new Audio(`/audio/${genre}/${genre}_hat.wav`), 
            R : new Audio(`/audio/${genre}/${genre}_cymbal.wav`),
            T : new Audio(`/audio/${genre}/${genre}_misc.wav`)
        })
    }

    const rnbAudio = makeAudioObj('rnb');
    const hiphopAudio = makeAudioObj('hiphop');
    const jazzAudio = makeAudioObj('jazz');
    const electronicAudio = makeAudioObj('electronic');

按键功能添加为:

    function pressKey(e) {
        let key = e.key.toUpperCase();
        if (sounds.loadState) {
            sounds[key].play();
        }
    }

    function setListener() {
        document.addEventListener('keypress', pressKey);
    }

    function resetListener() {
        document.removeEventListener('keypress', pressKey);
    }

最后,这被打包到一个函数中,由处理样式更改的按钮执行:

    const [firstLoad, setFirstLoad] = useState(false) // necessary to prevent removal of EventListener before it exists
    function kitSelection(genre, event) {
        if (firstLoad) {
            resetListener();
        }
        setSounds(genre);
        setListener();
        if (!firstLoad) {
            setFirstLoad(true);
        }
    }

    return (
        <div>
            <button onClick={e => kitSelection(rnbAudio, e)}>{'R&B'}</button>
            <button onClick={e => kitSelection(hiphopAudio, e)}>Hip-Hop</button>
            <button onClick={e => kitSelection(jazzAudio, e)}>Jazz</button>
            <button onClick={e => kitSelection(electronicAudio, e)}>Electronic</button>
        </div>
)

问题是 removeEventListener 不起作用,但与我发现的该站点上的其他帖子不一致。我认为这个问题与引用事件的事实有关pressKey,这意味着它试图删除与设置不同的功能。然而,将这些相同的 setListener/resetListener 函数放入页面其他位置的按钮形式(例如,处理添加和删除 EventListener 的按钮)确实有效,尽管引用pressKey方式相同。这让我很困惑我以什么方式实施这个错误。此外,如果这确实是问题,我不知道如何在不引用事件的情况下实现像我所追求的功能。

标签: javascriptreactjseventsevent-listener

解决方案


推荐阅读