【问题标题】:How to make onclick function execute only once?如何使onclick函数只执行一次?
【发布时间】:2019-08-27 20:36:07
【问题描述】:

我在一个按钮上有这个用于谷歌分析的代码。我需要它只执行一次,这样用户就无法通过多次按下按钮来更改统计信息。我尝试了类似主题的解决方案,但它们不起作用。请帮忙。这是我的代码。

<script>
    function klikaj(i) {
        gtag('event', 'first-4', {
            'event_category' : 'cat-4',
            'event_label' : 'site'
        });
    }

    document.body.addEventListener("click", klikaj(i), {once:true})
</script>


<div id="thumb0" class="thumbs" onclick="klikaj('rad1')">My button</div>

【问题讨论】:

  • 您发布的代码应该只运行一次监听器。如果它不起作用,请发布非工作 coe。您尝试过的其他解决方案是什么?他们在什么方面没有工作?请注意,您要附加两个侦听器:一个连接到正文,一个连接到按钮。
  • 请不要编辑您的问题以显示解决方案而不是问题;一旦您的问题得到解决,我们希望您在答案之一时用复选标记标记解决方案(就像您对 med morad's answer 所做的那样),或者如果不是,请回答您自己的问题(是的,这是允许的)。如果他们将来遇到与您类似的问题,这将使其对其他人更有帮助。谢谢。 ^_^
  • 只需在klikaj中设置禁用按钮
  • document.body.addEventListener("click", klikaj(i), {once:true})中,需要传递函数引用,而不是调用它。

标签: javascript html dom-events


【解决方案1】:

删除按钮上的 onclick 属性并通过 JavaScript 注册侦听器,就像您尝试做的那样:

<div id="thumb0" class="thumbs"
  style="border: 1px solid; cursor: pointer; float: left">
    My button
</div>
<script>
    function klikaj(i) {
        console.log(i);
    }
    document.getElementById('thumb0')
        .addEventListener("click", function(event) {
            klikaj('rad1');
        }, {once: true});
</script>

如果您的浏览器不支持{ once: true } 选项,您可以手动移除事件监听器:

<div id="thumb0" class="thumbs"
  style="border: 1px solid;cursor: pointer;float:left">
    My button
</div>

<script>
    function klikaj(i) {
        console.log(i);
    }
    function onClick(event) {
      klikaj('rad1');
      document
        .getElementById('thumb0')
        .removeEventListener("click", onClick);
    }
    
    document
      .getElementById('thumb0')
      .addEventListener("click", onClick);
</script>

【讨论】:

  • 事件监听器在触发后是否从元素中移除?
  • 很遗憾,IE 和 Edge 不支持 once: true
  • 是的,由于选项参数{ once: true },它被删除了。你可以在MDN阅读它
  • @sunknudsen 那你为什么在你的代码示例中使用{ once: true },如果你必须支持IE?
  • 感谢您的回答,但不幸的是,此代码(两个选项)由于某种原因没有向 Google 分析器发送事件,就像我所做的那样
【解决方案2】:

你可以像这样使用removeAttribute()document.getElementById('thumb0').removeAttribute("onclick");

或者你可以让函数像这样返回 false:document.getElementById('thumb0').onclick = ()=&gt; false

【讨论】:

  • 感谢您的回答,但不幸的是,这段代码没有再次停止执行。我理解正确吗?
  • 这是一个工作示例 ```
    点击我
    ```
【解决方案3】:

我建议设置一个变量并检查它的值。

<script>
    var clicked = false;
    function klikaj(i) {
        if (clicked === false) {
            gtag('event', 'first-4', {
                'event_category' : 'cat-4',
                'event_label' : 'site'
            });
        }
        clicked = true;
    }
    ...
</script>

或者按照其他人的建议删除onclick事件,

<script>
    function klikaj(i) {
        gtag('event', 'first-4', {
            'event_category' : 'cat-4',
            'event_label' : 'site'
        });
        document.getElementById('thumb0).onclick = undefined;
    }
    ...
</script>

请注意,很遗憾,IE 和 Edge 不支持 once: true。见https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

【讨论】:

  • 最好去掉监听器。
  • 感谢您的回答,但不幸的是,由于某种原因,此代码也没有像我一样将事件发送到 Google 分析
  • 嗨@Alex,gtag 变量的值和类型是什么。您可以通过添加 console.log(gtag, typeof gtag); 来获取它们。就在您调用 gtag 函数之前。
  • 您是否有您的代码的生产(实时)示例,我们可以查看配置 Google Analytics 的位置?
【解决方案4】:

事件处理程序和监听器

将事件注册到元素有三种方法*。以下示例展示了如何将点击事件注册到具有类.once** 的链接,该类在触发时调用函数test()

  1. 事件监听器(推荐)
    • document.querySelector('.once').addEventListener('click', test);`
  2. 事件属性(推荐)
    • &lt;a href='#/' class='once'onclick='test()'&gt;Click&lt;/a&gt;
  3. 事件属性
    • document.querySelector('.once').onclick = test;`

*DOM on-event handlers for details
** .once 类与#2 无关


问题

OPO原始Post)有一个事件监听器(参见上面的#1)注册&lt;body&gt; 标记的点击事件和事件属性(参见上面的#2)将点击事件注册到&lt;div&gt;。每个人都调用一个名为klikaj() 的函数(又名回调函数),这是多余的。当您打算让用户单击 div 时,单击正文(通常无处不在)没有用。如果用户单击除 div 之外的任何位置,klikaj() 将被调用。如果用户单击 div,klikaj() 将被调用两次。我建议您删除这两个事件处理程序并将它们替换为:

A.

document.getElementById('thumb0').addEventListener("click", klikaj);

请注意klikaj 没有括号(),因为浏览器将() 解释为现在运行函数,而不是在用户触发注册事件时运行(参见上面的#1 和#3)。如果事件处理程序有额外的语句和/或回调函数,那么应该在它周围包裹一个匿名函数并应用正常语法:

B.

document.getElementById('thumb0').addEventListener("click", function(event) { 
  klikaj();
  console.log('clicked');
});

一个更简洁的替代方法是在回调函数的定义中添加额外的行,并注册像 #A 这样的事件。


解决方案

只需在klikaj()的最后一行添加以下语句:

this.style.pointerEvents = "none";

这将使点击的标签无法点击。应用于 OP 代码应该是这样的:

<div id="thumb0" class="thumbs">Thumb 0</div>
<script>
  function klikaj(event) {
    gtag('event', 'first-4', {
      'event_category' : 'cat-4',
      'event_label' : 'site'
    });
    this.style.pointerEvents = "none";   
  }

  document.getElementById('thumb0').addEventListener("click", klikaj);
</script>


演示

下面的demo有两个链接:

  1. .default - 注册到点击事件的普通链接,当 触发调用test()

  2. .once - 注册到点击事件的链接,触发时 调用test() 并呈现链接不可点击。

function test() {
  console.log('test');
}

document.querySelector('.default').onclick = function(e) {
  test();
}

document.querySelector('.once').onclick = function(e) {
  test();
  this.style.pointerEvents = 'none';
}
<a href='#/' class='default'>Default</a><br>
<a href='#/' class='once'>Once</a>

【讨论】:

    【解决方案5】:

    您尝试附加处理程序函数的方式存在问题。 klikaj(i) 函数返回 undefined,因此您将 undefined 附加到按钮。如果您想在单击按钮时执行klikaj(i),请将其放在闭包中,如下所示:

    const button = document.querySelector('button')
    const i = 10
    function klikaj(i) {console.log('clicked once')}
    
    button.addEventListener('click', () => { klikaj(i) }, {once: true})
    &lt;button&gt;Hello world&lt;/button&gt;

    如果浏览器不支持{once: true},你可以使用:

    const button = document.querySelector('button')
    const i = 10
    function klikaj(i) {console.log("clicked once")}
    
    function clickOnceHandler(event) {
      klikaj(i)
      event.currentTarget.removeEventListener('click', clickOnceHandler)
    }
    
    button.addEventListener('click', clickOnceHandler)
    &lt;button&gt;Hello world&lt;/button&gt;

    【讨论】:

      【解决方案6】:

      只需使用一个标志变量并在第一次执行时设置它:

      var handlerExecuted = false;
      function clickHandler() {
        if (!handlerExecuted) {
          console.log("call gtag() here");
          handlerExecuted = true;
        } else {
          console.log("not calling gtag() function");
        }
      }
      document
        .getElementById("thumb0")
        .addEventListener("click", clickHandler);
      &lt;div id="thumb0" class="thumbs"&gt;My button&lt;/div&gt;

      使用闭包的高级变体,可用于多个按钮:

      function clickHandlerFactory() {
        var handlerExecuted = false;
        return function() {
          if (!handlerExecuted) {
            console.log("call gtag() here");
            handlerExecuted = true;
          } else {
            console.log("not calling gtag() function");
          }
        }
      }
      [...document.querySelectorAll(".thumbs")].forEach(function(el) {
        el.addEventListener("click", clickHandlerFactory());
      });
      <div id="thumb0" class="thumbs">Button 1</div>
      <div id="thumb1" class="thumbs">Button 2</div>

      【讨论】:

        【解决方案7】:

        如果您希望仅在用户单击按钮时调用该函数,则必须从主体中删除单击事件侦听器。

        只有在您可以更改函数体内的 klikaj 函数定义时才触发 gtag 函数。第一次调用后,gtag 将永远不会被调用。

        下面的代码可以正常工作。

        <script>
            function klikaj(i) {
                gtag('event', 'first-4', {
                    'event_category' : 'cat-4',
                    'event_label' : 'site'
                });
                klikaj = function() {};
            }
        </script>
        
        
        <div id="thumb0" class="thumbs" onclick="klikaj('rad1')">
            My button
        </div>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-22
          • 1970-01-01
          • 1970-01-01
          • 2018-02-05
          • 1970-01-01
          • 1970-01-01
          • 2023-02-04
          相关资源
          最近更新 更多