输入类型复选框,标签触发事件两次

问题描述 投票:7回答:4

我试图通过tickMark动态创建圆形复选框,这些复选框附加到id="demo" onclick两个按钮,调用get(data)方法。

问题是当两个按钮同时调用时,复选框没有得到刻度线并导致调用qazxsw poi方法两次或更多次,如console.log中所示。

但是,我正在使用getdata(idD + '_chckBox')

这里有什么问题,e.preventDefault(); e.stopPropagation();被调用两次或更多次并且圆形检查框没有被检查?

我正在尝试切换复选框并显示刻度线。如果有任何更好的方法可以做到这一点,也欢迎。

什么是在for循环中动态htmls中绑定getdata(idD + '_chckBox')onclick方法的最佳和最简单的方法,以便对象可以作为参数在被调用方法onclick中传递。

index.html

onscroll
   

     var data0 = [{
            "title": "a"
          },
          {
            "title": "b"
          },
          {
            "title": "c"
          },
          {
            "title": "d"
          },
        ];
        var data1 = [{
            "title": "ads"
          },
          {
            "title": "bd"
          },
          {
            "title": "fc"
          },
          {
            "title": "dg"
          },
        ];
    
     var html = "<div id='parent'   ' + 'onscroll="loadMoreContent(event)" ></div>";
     $(html ).appendTo('body');
        $(document).on('click', '#btn11', () => {
          get(data0, 'parent');
        })
        $(document).on('click', '#btn00', () => {
          get(data1,'parent');
        })
    
function loadMoreContent(event){
 // gettting server data (data01 ) on ajax call
var data01 = [{
            "title": "aaa"
          },
          {
            "title": "sdw3b"
          },
          {
            "title": "c433"
          },
          {
            "title": "34d"
          },
        ];
get(data01 , idToAppend)
}
        function get(data, idToAppend) {
    
          var html = '';
          html += '<div class="col-12 parentdiv">';
          $.each(data, function(key, msgItem) {
            var idD = msgItem.title + key;
            html += '<div class="flLeftBlock"  style="width: 30px;margin-top: 36px;">';
            html += '<div class="roundCheckboxWidget"  id="' + idD + '_roundCheckboxWidget">';
            html += '<input   id="' + idD + '_chckBox" class="" type="checkbox" tid="" title="discard">';
            html += '<label id="' + idD + '_chckBox_label" for="' + msgItem.title + '" ></label> ';
            html += "&nbsp;" + msgItem.title;
            html += '</div>';
            html += '</div>';
            html += '';
          });
          html += '</div>';
          $('#'+ idToAppend).append(html);
    
          $.each(data, function(index, element) {
            var idD = element.title + index;
            const self = this;
            $(document).on('click', '#' + idD + '_chckBox_label', (e) => {
              if (e.target.tagName === "LABEL") {
                e.preventDefault();
                e.stopPropagation();
                console.log('#' + idD + '_chckBox_label');
                getdata(idD + '_chckBox');
              }
            });
          });
        }
    
        function getdata(id) {
          console.log(id);
          $("#" + id).prop("checked", !$("#" + id).prop("checked"));
          return true;
        }
.roundCheckboxWidget {
  position: relative;
}

.roundCheckboxWidget label {
  background-color: #ffffff;
  border: 1px solid rgb(196, 196, 209);
  border-radius: 50%;
  cursor: pointer;
  height: 22px;
  left: 0;
  position: absolute;
  top: 0;
  width: 22px;
}

.roundCheckboxWidget label:after {
  border: 2px solid #fff;
  border-top: none;
  border-right: none;
  content: "";
  height: 6px;
  left: 4px;
  opacity: 0;
  position: absolute;
  top: 6px;
  transform: rotate(-45deg);
  width: 12px;
}

.roundCheckboxWidget input[type="checkbox"] {
  visibility: hidden;
}

.roundCheckboxWidget input[type="checkbox"]:checked+label {
  /* background-color: #6168e7 !important;
      border-color: 1px solid #6168e7 !important; */
}

.roundCheckboxWidget input[type="checkbox"]:checked+label:after {
  opacity: 1;
}

.roundCheckboxWidget input[type="checkbox"]:checked+label {
  background-color: #ff5b6a;
  border-color: #ff5b6a !important;
}
javascript jquery html css
4个回答
4
投票

这里有几个错误。

  1. 你使用一些不独特的<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <p>Alternate click on two buttons without refreshing causing getdata() method call twice. </p> <button id="btn11" onclick="get()">Try It</button> <button id="btn00" onclick="get()">Try It2</button> <div id="demo"></div>。尝试使它们独一无二,但是你使用了静态的数组id。因此,在每次单击按钮时,都会生成重复的ID。你需要一个柜台。
  2. 您使用key循环来定义委托事件处理程序...这是对委派的误解。
  3. .each()上的checkbox属性可以在没有单行代码的情况下执行此操作时,您可以使用函数来切换for=状态。
  4. label函数不清楚...我假设你想要一个“无限滚动”...所以你必须检查是否到达页面的底部以调用Ajax请求...否则,你将发出大量的请求每个卷轴......上下!

所以这是如何做到的: (见代码内的评论)

loadMoreContent()
// checkbox title arrays
var data0 = [{ "title": "a" }, { "title": "b" }, { "title": "c" }, { "title": "d" }];
var data1 = [{ "title": "ads" }, { "title": "bd" }, { "title": "fc" }, { "title": "dg" }];

// Appends th "parent" div on load.
var html = "<div id='parent'></div>";
$(html).appendTo('body');

// Button handlers
$(document).on('click', '#btn11', () => {
  get(data0,'parent');
})
$(document).on('click', '#btn00', () => {
  get(data1,'parent');
})

// Simulated Ajax request... I assume.
function loadMoreContent(idToAppend){
  // gettting server data (data01 ) on ajax call
  var data01 = [{ "title": "aaa" }, { "title": "sdw3b" }, { "title": "c433" }, { "title": "34d" } ];
  get(data01 , idToAppend)
}

// Main function. It needs a counter to create UNIQUE ids.
var checkbox_counter = 0;
function get(data, idToAppend) {

  var html = '';
  html += '<div class="col-12 parentdiv">';
  $.each(data, function(key, msgItem) {
    html += '<div class="flLeftBlock" style="width: 30px;margin-top: 36px;">';
    html += '<div class="roundCheckboxWidget">';
    html += '<input id="checkbox_'+checkbox_counter+'" type="checkbox" tid="" title="discard">';
    html += '<label for="checkbox_'+checkbox_counter+'"></label> ';
    html += "&nbsp;" + msgItem.title;
    html += '</div>';
    html += '</div>';
    html += '';
    
    // Increment the checkbox counter
    checkbox_counter++;
  });
  html += '</div>';
  $('#'+ idToAppend).append(html);
}

// Just to console log the id of the checkbox...
$(document).on('click', 'label', function(){
  var checkbox_id = $(this).prev("[type='checkbox']").attr("id");
  console.log(checkbox_id);
});

// On scroll handler, check if the bottom of the page is reached to load some more...
$(document).on('scroll', function(){
  var scrolled = Math.ceil($(window).scrollTop());
  var viewport_height = $(window).outerHeight();
  var window_full_height = $(document).outerHeight();
  //console.log(scrolled +" "+ viewport_height +" "+ window_full_height);
  
  if(scrolled + viewport_height == window_full_height){
    console.log("reached the bottom... Loading some more!");
    
    // Call the Ajax request
    loadMoreContent("parent");
  }
});
.roundCheckboxWidget {
  position: relative;
}

.roundCheckboxWidget label {
  background-color: #ffffff;
  border: 1px solid rgb(196, 196, 209);
  border-radius: 50%;
  cursor: pointer;
  height: 22px;
  left: 0;
  position: absolute;
  top: 0;
  width: 22px;
}

.roundCheckboxWidget label:after {
  border: 2px solid #fff;
  border-top: none;
  border-right: none;
  content: "";
  height: 6px;
  left: 4px;
  opacity: 0;
  position: absolute;
  top: 6px;
  transform: rotate(-45deg);
  width: 12px;
}

.roundCheckboxWidget input[type="checkbox"] {
  visibility: hidden;
}

.roundCheckboxWidget input[type="checkbox"]:checked+label {
  /* background-color: #6168e7 !important;
  border-color: 1px solid #6168e7 !important; */
}

.roundCheckboxWidget input[type="checkbox"]:checked+label:after {
  opacity: 1;
}

.roundCheckboxWidget input[type="checkbox"]:checked+label {
  background-color: #ff5b6a;
  border-color: #ff5b6a !important;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <p>Alternate click on two buttons without refreshing causing getdata() method call twice. </p> <button id="btn11" onclick="get()">Try It</button> <button id="btn00" onclick="get()">Try It2</button> <div id="demo"></div>


2
投票

代码有两个问题:

  • 您正在设置CodePen并使用jQuery添加onclick="get()"事件,因此它将触发两次。删除click
  • 第二个问题是,在每个onclick ="get()"调用它将添加新的get()监听器复选框。为了防止在数组中使用布尔值,只应用click事件一次

click
var data0 = [{
    "title": "a"
  },
  {
    "title": "b"
  },
  {
    "title": "c"
  },
  {
    "title": "d"
  },
  false
];
var data1 = [{
    "title": "ads"
  },
  {
    "title": "bd"
  },
  {
    "title": "fc"
  },
  {
    "title": "dg"
  },
  false
];
$(document).on('click', '#btn11', () => {
  get(data0);
})
$(document).on('click', '#btn00', () => {
  get(data1);
})

function get(data) {
  var html = '';
  html += '<div class="col-12 parentdiv"';
  $.each(data, function(key, msgItem) {
    var idD = msgItem.title + key;
    html += '<div class="flLeftBlock"  style="width: 30px;margin-top: 36px;">';
    html += '<div class="roundCheckboxWidget"  id="' + idD + '_roundCheckboxWidget">';
    html += '<input   id="' + idD + '_chckBox" class="" type="checkbox" tid="" title="discard">';
    html += '<label id="' + idD + '_chckBox_label" for="' + msgItem.title + '" ></label> ';
    html += "&nbsp;" + msgItem.title;
    html += '</div>';
    html += '</div>';
    html += '';
  });
  html += '</div>';
  $('#demo').html(html);
  if(data[data.length - 1]) return false;
  
  $.each(data, function(index, element) {
    var idD = element.title + index;
    const self = this;
    if(index === data.length - 1) return false;
    $(document).on('click', '#' + idD + '_chckBox_label', (e) => {
      if (e.target.tagName === "LABEL") {
        e.preventDefault();
        e.stopPropagation();
        //console.log('#' + idD + '_chckBox_label');
        getdata(idD + '_chckBox');
      }
    });
    
  });
  data[data.length -1] = true;
}

function getdata(id) {
  //console.log(id);
  $("#" + id).prop("checked", !$("#" + id).prop("checked"));
  return true;
}
.roundCheckboxWidget {
  position: relative;
}

.roundCheckboxWidget label {
  background-color: #ffffff;
  border: 1px solid rgb(196, 196, 209);
  border-radius: 50%;
  cursor: pointer;
  height: 22px;
  left: 0;
  position: absolute;
  top: 0;
  width: 22px;
}

.roundCheckboxWidget label:after {
  border: 2px solid #fff;
  border-top: none;
  border-right: none;
  content: "";
  height: 6px;
  left: 4px;
  opacity: 0;
  position: absolute;
  top: 6px;
  transform: rotate(-45deg);
  width: 12px;
}

.roundCheckboxWidget input[type="checkbox"] {
  visibility: hidden;
}

.roundCheckboxWidget input[type="checkbox"]:checked+label {
  /* background-color: #6168e7 !important;
      border-color: 1px solid #6168e7 !important; */
}

.roundCheckboxWidget input[type="checkbox"]:checked+label:after {
  opacity: 1;
}

.roundCheckboxWidget input[type="checkbox"]:checked+label {
  background-color: #ff5b6a;
  border-color: #ff5b6a !important;
}

2
投票

TL; DR

在绑定新事件之前取消绑定事件处理程序。使用此代码:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <p>Alternate click on two buttons without refreshing causing getdata() method call twice. </p> <button id="btn11">Try It</button> <button id="btn00">Try It2</button> <div id="demo"></div>

答案很长

你不能使用$(document).off('click', '#' + idD + '_chckBox_label').on('click', '#' + idD + '_chckBox_label', (e) => {来停止不同的函数调用。这是事情,

假设你的dom中有一个元素,并且你添加了两次事件处理程序,在这种情况下,无论如何都将执行这两个事件处理程序。

你需要的是,

“在添加新的点击处理程序之前删除它”。

这一行:

e.preventDefault(); e.stopPropagation();为标签添加了事件处理程序。但是当您再次单击某个按钮时,会再次运行并添加另一个事件处理程序。

因此,您单击按钮的次数与您添加到元素中的事件处理程序数相同。

但是当你刷新时,它是固定的。原因:刷新页面会加载一个全新的页面,所有以前的处理程序都消失了。您需要以编程方式执行此操作,以下是您可以执行此操作的方法。

$(document).on('click', '#' + idD + '_chckBox_label', (e) => {

此代码告诉您,关闭任何以前的单击处理程序并添加一个新处理程序。

奖金:

如果已命名函数,则可以删除特定事件处理程序,例如:

$(document).off('click', '#' + idD + '_chckBox_label').on('click', '#' + idD + '_chckBox_label', (e) => {

希望这可以帮助。如果您有任何反问题,请告诉我。

PS:当我复制粘贴时代码中有一些拼写错误,但我认为运行代码不是这里的议程:)


0
投票

这里有2个点击事件监听器:

$(document).off(<event_type>, <el_selector>, <event_handler>).on(<event_type>, <el_selector>, <event_handler>);

你的qazxsw poi函数包含两个qazxsw poi循环,第二个是在这里添加另一个事件监听器:

$(document).on('click', '#btn11', () => {
  get(data0);
})
$(document).on('click', '#btn00', () => {
  get(data1);
})

据我所知,当你点击第二个按钮时,可能有3个事件监听器响应该事件。

© www.soinside.com 2019 - 2024. All rights reserved.