JS问题。为啥onclick事件单击一次后,在页面无刷新的情况下,单击第二次无效?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS问题。为啥onclick事件单击一次后,在页面无刷新的情况下,单击第二次无效?相关的知识,希望对你有一定的参考价值。

JS问题。为什么onclick事件单击一次后,在页面无刷新的情况下,单击第二次无效?如何能重复onclick。并且能让function重复执行?

参考技术A onclick 注册了就会一直有效,你说那种单击一次就失效情况,反而要用专门写个释放动作才会出现。估计,单击一次后代码出错。后面单击就无效了 参考技术B 这是一个死判断嘛,相当于你自己把按钮禁用了。 参考技术C 你是要点一次就反复执行一个函数?试试setTimeout("function",time); 参考技术D 根据你描述,是你代码写的有问题,上代码 第5个回答  2013-10-11 把代码贴上来吧,这样好针对问题讲啊

阻止单击一次 span 元素上的 onClick 事件

【中文标题】阻止单击一次 span 元素上的 onClick 事件【英文标题】:Prevent an onClick event on a span element when it was clicked once 【发布时间】:2021-02-24 19:26:17 【问题描述】:

我正在构建一个游戏,您必须在其中单击十字象形图或检查象形图,具体取决于答案是正确还是错误。但是一旦你回答了你就不能再点击这两个象形图中的任何一个(即使是你没有点击的那个)。

为了做到这一点,我在包含象形图的元素上使用了 useRef,并尝试禁用该元素。它没有用。 我也试图让他们的父元素“不可改变”,但它也没有工作

我将不胜感激。谢谢

const pictoAnswer = useRef()
const divParent = useRef()

pictoAnswer.current.disabled = true
divParent.current.pointerEvents = "none"

全貌

import React,  useState, useRef  from "react";

// modules
import  FontAwesomeIcon  from "@fortawesome/react-fontawesome";
import  faCheck, faTimes  from "@fortawesome/free-solid-svg-icons";

const WordList = () => 
  const liBgColor = useRef();
  const pictoAnswer = useRef();
  const divParent = useRef();

  // change the color bg of the list element
  const isCorrect = (answer) => 
    if (answer) 
      liBgColor.current.style.backgroundColor = "#5DCF36";
     else 
      liBgColor.current.style.backgroundColor = "#d15f5f";
    
  ;

  //list of word to make guess
  let wordsToGuess = ["chambre", "salon", "rire", "fusée"];
  const numberOfWordToGuess = wordsToGuess.length;

  const [indexWord, setIndexWord] = useState(1);
  console.log("indexWord:", indexWord);
  const [wordToDisplay, setWordToDisplay] = useState([wordsToGuess[0]]);

 
  // push the next word to guess into the wordToDisplay array
  const handleAnswer = (answer) => 
   

    pictoAnswer.current.disabled = true;
    divParent.current.pointerEvents = "none";
    //set the new index of the word item
    setIndexWord(indexWord + 1);
    //change the bgColor depending on the answer
    isCorrect(answer);
    //would display the next word or not
    if (indexWord == numberOfWordToGuess || indexWord > numberOfWordToGuess) 
      console.log("no more word to guess");
     else 
      setWordToDisplay([...wordToDisplay, wordsToGuess[indexWord]]);
    
  ;

  return (
    <ul className="word__list">
      wordToDisplay.map((word, i) => (
        <li key=i className="word__item" ref=liBgColor>
          <p className="word">word</p>
          <div className="icon-box" ref=divParent>
            <span
              ref=pictoAnswer
              onClick=() => 
                handleAnswer(false);
              
            >
              <FontAwesomeIcon icon=faTimes color="#FF5252" />
            </span>
            <span
              ref=pictoAnswer
              onClick=() => 
                handleAnswer(true);
              
            >
              <FontAwesomeIcon icon=faCheck color="#008000" />
            </span>
          </div>
        </li>
      ))
    </ul>
  );
;

export default WordList;

codeSandBox

【问题讨论】:

document.querySelector("span").addEventListener("click", function(e) e.preventDefault(); return false; , once : true); 没有足够的信息可以确定,但是您至少应该检查带有图片的组件没有被卸载和重新安装,因为这将重置其禁用/启用状态。 不应该阻止进一步的点击注册,如果它被回答,你不应该传递任何 onClick 处理程序,所以点击不会做任何事情。或者,您可以检查处理程序中的已回答状态,如果为真,则退出任何进一步的操作。 你为什么不使用语义按钮(带有disabled 属性)?您的 React ref 用法似乎不正确,因为只有最后一个映射的 word 元素附加了 ref,您甚至在同一渲染中分配了两次 pictoAnswer ref(!!)。 indexWord 不会是 handleAnswer 中的增量值,但也许这没问题 (???) 虽然我怀疑不是因为您稍后尝试推送一个新单词以显示 @987654329 @。当您应该使用 classNamestyle 设置任何样式(而不是 DOM 操作)时,似乎误用了 React refs。 您能否为此代码创建一个 running 代码框,以便我们更好地了解您要完成的工作? 【参考方案1】:

您的代码的主要问题是不正确地使用 React refs 来操作 DOM 元素。

解决方案

    存储一个初始化为空值的“已解决”状态数组,以指示单词是否已被标记为真/假。相同的条件用于防止进一步的“点击”处理。 使用 CSS 设置列表项的样式。 更新handleAnswer 以设置“已解决”状态并增加单词索引。 使用useEffect 挂钩更新要显示的字词。

代码:

const wordsToGuess = ["chambre", "salon", "rire", "fusée"];

const App = () => 
  const [indexWord, setIndexWord] = useState(0);
  const [wordToDisplay, setWordToDisplay] = useState([]);
  const [settled, setSettled] = useState(Array(wordsToGuess.length).fill(null));

  useEffect(() => 
    setWordToDisplay(wordsToGuess.slice(0, indexWord + 1));
  , [indexWord]);

  const handleAnswer = (index, answer) => () => 
    if (settled[index] === null) 
      setSettled((settled) =>
        settled.map((el, i) => (i === indexWord ? answer : el))
      );
      if (indexWord < wordsToGuess.length - 1) setIndexWord((i) => i + 1);
    
  ;

  return (
    <ul className="word__list">
      wordToDisplay.map((word, i) => (
        <li
          key=i
          className=classNames("word__item", 
            "settled-true": settled[i] === true,
            "settled-false": settled[i] === false
          )
        >
          <p className="word">word</p>
          <div className="icon-box">
            <span onClick=handleAnswer(i, false)>
              <FontAwesomeIcon icon=faTimes color="#FF5252" />
            </span>
            <span onClick=handleAnswer(i, true)>
              <FontAwesomeIcon icon=faCheck color="#008000" />
            </span>
          </div>
        </li>
      ))
    </ul>
  );
;

CSS:

.settled-true 
  background-color: #5dcf36;


.settled-false 
  background-color: #d15f5f;

演示

【讨论】:

以上是关于JS问题。为啥onclick事件单击一次后,在页面无刷新的情况下,单击第二次无效?的主要内容,如果未能解决你的问题,请参考以下文章

为啥单击 1 次后此按钮无用?

如何让一个按钮自动触发,自动执行onclick鼠标单击事件. 默认已点击.

JS5(事件)

JS事件-让网页交互

jQuery 在第一次切换后仅在 Safari iOS5 中单击 3 次后触发

JS问题 为啥我直接在onclick后写window.close不加函数,打开的时候直接闪退了?加不加函数有区别吗