【问题标题】:How to make sure that click functions are only performed once如何确保点击功能只执行一次
【发布时间】:2015-08-13 15:08:47
【问题描述】:

当用户点击.class#id时,两个div的css都会发生一些变化,#id的值会增加1。但是,当用户点击其中一个div时, 更改只应进行一次 - 如果用户再次单击,除非刷新页面,否则不会发生任何事情。

$('.class, #id').one('click', function(e) {
   $('.class, #id').css({
   'background-color' : 'rgb(232,69,73)',
   'color' : '#fff',
   });
 $("#id").html(function(i, val) { return val*1+1 });
 });

上面显示了我正在使用的代码。如您所见,我使用.one 来确保代码只执行一次。这可行,但问题是用户可以点击.class,然后点击#div,这意味着代码可以执行两次

我将如何编辑它以使代码只能执行一次 - 单击一个 div 意味着无法单击另一个 div。

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    您可以在两个对象上设置数据属性,如果未设置,则仅增加计数器:

    $('.class, #id').one('click', function(e) {
       if (!$(this).data("valueSet")) {
           $('.class, #id').css({
               'background-color' : 'rgb(232,69,73)',
               'color' : '#fff'
           }).data("valueSet", true);
           $("#id").html(function(i, val) { return val*1+1 });
        }
     });
    

    或者,如果您知道没有要保留的其他 jQuery 点击处理程序,您可以解除所有 jQuery 点击处理程序与这两个对象的绑定

    $('.class, #id').one('click', function(e) {
        $('.class, #id').off("click").css({
            'background-color' : 'rgb(232,69,73)',
            'color' : '#fff'
        })
        $("#id").html(function(i, val) { return val*1+1 });
     });
    

    或者,您可以通过将事件处理程序放在命名函数中仅解除绑定此特定事件处理程序

    function oneClick(e) {
        $('.class, #id').off("click", oneClick).css({
            'background-color' : 'rgb(232,69,73)',
            'color' : '#fff'
        })
        $("#id").html(function(i, val) { return val*1+1 });
    }
    
    $('.class, #id').one('click', oneClick);
    

    更通用一点的方案会创建一个只执行一次操作的自定义函数:

    function oneAction(fn) {
         var calledYet = false;
         return function() {
              if (!calledYet) {
                  calledYet = true;
                  return fn.apply(this, arguments);
              }
         }
     }
    

    然后,你可以使用这个:

    $('.class, #id').one('click', oneAction(function(e) {
        // this will only ever be executed once
        $('.class, #id').css({
            'background-color' : 'rgb(232,69,73)',
            'color' : '#fff'
        })
        $("#id").html(function(i, val) { return val*1+1 });
    }));
    

    【讨论】:

    • 我想我会选择使用带有事件委托的one,因为它不会保留处理程序。不仅如此,一些提议的解决方案也无法与其他处理程序配合使用。如果你想手动调用off,我会选择一个可以在off中引用的命名函数表达式。
    • @plalx - 我提供了三种不同的选择,它们可以很好地与其他点击处理程序配合使用,并记录了不能使用的选项。您的委托选项很有创意。
    • 没错,我想我只关注你答案的一部分;我的坏;)
    【解决方案2】:

    我认为您可以改用事件委托。这样你就有一个处理所有目标的处理程序,一旦调用,jQuery 会自动删除它。

    $(document).one('click', '#first,#second', alert.bind(null, 'clicked'));
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="first">first</button>
    <button id="second">second</button>

    使用您的代码将是:

    $(document).one('click', '.class, #id', function(e) {
        //handle click
    });
    

    这是另一个示例,展示了如何在调用后使用命名函数表达式以安全的方式(不影响其他处理程序)手动删除处理程序:

    $('#first, #second').click(function someClickHandler(e) {
      alert('clicked!');
      
      $('#first, #second').off('click', someClickHandler);
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="first">First</button>
    <button id="second">Second</button>

    【讨论】:

      【解决方案3】:

      实际上,您正在设置两个侦听器。一个在.class,另一个在#id

      这意味着您需要存储一个状态变量并在执行任何操作之前对其进行检查。

      var isClickable = true;
      $('.class, #id').one('click', function(e) {
         if(isClickable){
           isClickable = false;
           $('.class, #id').css({
           'background-color' : 'rgb(232,69,73)',
           'color' : '#fff',
           });
         $("#id").html(function(i, val) { return val*1+1 });
        }
       });
      

      这比向实际的 DOM 元素添加 state 属性更好。

      【讨论】:

      • 为什么创建一个全局变量比给每个DOM元素添加一个状态属性更好?
      • 更新 DOM 比在内存中存储变量更昂贵。
      猜你喜欢
      • 2019-11-12
      • 1970-01-01
      • 2012-08-25
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 2021-11-17
      • 2017-11-24
      • 1970-01-01
      相关资源
      最近更新 更多