猿问

单击事件侦听器调用的函数在不单击的情况下被调用,但仅在第二次运行时调用

这是一个谜题:


我正在尝试创建一个简单的选择你自己的路径游戏,它从本地 JSON 文件中获取内容。运行时,它将每个场景(JSON 文件中的“Section”)分解为多个段落,并将第一个段落添加到 DOM,并在其周围的 div 上附加一个事件侦听器。每次用户单击“容器”时,都会从该部分添加另一个段落,直到显示所有段落。


之后,如果用户再次单击“容器”,则会添加三个选项,每个选项都附加了自己的事件侦听器。单击这些选项之一时,场景(或“部分”)将更改为选定的选项。HTML“容器”被清空,该过程通过添加新场景(部分)的第一段重新开始。


问题是它对第一部分和选项工作正常,但是在用户单击选项后,它会加载新场景的两段而不是一个。它应该加载一个段落并等待点击事件,但它实际上加载了一秒钟。第二段是通过 readyToUpdate 函数加载的,该函数只能由事件侦听器调用(尚未触发)。


{  

    "Section_1": {

        "Content": "Dark corner paragraph one<>Dark corner paragraph two<>Dark corner paragraph three",

        "Choices": [

            "Go to the garden<>24",

            "Go to the terrace<>95",

            "Go to the beach<>145"

        ]


    },


    "Section_24": {

        "Content": "Garden paragraph one<>Garden paragraph two<>Garden paragraph three",

        "Choices": [

            "Go to the dark corner<>1",

            "Go to the terrace<>95",

            "Go to the beach<>145"

        ]

    },


    "Section_95": {

        "Content": "Terrace paragraph one<>Terrace paragraph two<>Terrace paragraph three",

        "Choices": [

            "Go to the dark corner<>1",

            "Go to the garden<>24",

            "Go to the beach<>145"

        ]

    },


    "Section_145": {

        "Content": "Beach paragraph one<>Beach paragraph two<>Beach paragraph three",

        "Choices": [

            "Go to the dark corner<>1",

            "Go to the garden<>24",

            "Go to the terrace<>95"

        ]

    }

}

    <div id="container"></div>


MMTTMM
浏览 160回答 2
2回答

慕容森

我相信正在发生的事情是,当您单击一个选项并调用选项单击侦听器时,您正在经历update()并向updateParagraphs()容器添加一个新的单击侦听器。但与此同时,click 事件正在传播到容器,并被您刚刚添加的新容器侦听器捕获。所以你有两个选择:第一个,正如@wth193 所建议的,是使用 setTimeout() 在下一个滴答声中添加容器监听器。function updateParagraphs(){&nbsp; &nbsp; // ...&nbsp; &nbsp; // container.addEventListener('click', readyToUpdate, {once: true});&nbsp; &nbsp; setTimeout(function () {&nbsp; &nbsp; &nbsp; &nbsp; container.addEventListener('click', readyToUpdate, {once: true});&nbsp; &nbsp; });}在我看来,一个更干净(更清晰)的解决方案是使用Event.stopPropagation()。function choiceUpdater(e){&nbsp; console.log("Enter choiceUpdater");&nbsp; e.stopPropagation();&nbsp; // ...}这样,click 事件仅由选择元素捕获,而不是由容器捕获。

慕莱坞森

function updateParagraphs(){&nbsp; &nbsp; ...&nbsp; &nbsp; // container.addEventListener('click', readyToUpdate, {once: true});&nbsp; &nbsp; setTimeout(function () {&nbsp; &nbsp; &nbsp; &nbsp; container.addEventListener('click', readyToUpdate, {once: true});&nbsp; &nbsp; });}我认为打破调用堆栈的 setTimeout 似乎有效,但我无法解释原因。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答