从最近的.change()事件

时间:2017-08-22 21:28:17

标签: javascript jquery onclick click onchange

我在解决一个基本问题时遇到了麻烦,但是甚至无法弄清楚研究的正确用语是什么。

本质上,我有一个.change()监听器,用于监听div内的复选框的更改(它们切换Leaflet Map图层)。我想创建一个变量来保存已选中复选框的列表。我可以这样做,但是,对于.change()侦听器触发的每一次,它似乎都会保留检查哪些图层的各个实例。一些应该重新创建问题的代码:

var lyrs;

$("div#myID input:checkbox").change(function() {
    lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
    console.log('in .change(): ', lyrs)
    legendFunction( lyrs );

});

function legendFunction( lyrs ) {
    map.on('click', function() {
        console.log('in legendFunction: ', lyrs);
    });
};

当我在.change回调函数中将变量打印到控制台时,存在单个lyrs对象。但是,当我从.on('click')中的legendFunction回调函数打印它时,它会打印一个列表(缺少更好的单词),每次检查或取消选中复选框时都会检查这些图层。下图显示了这一点:

enter image description here

发生了什么事?如何让lyrs函数中的.on('click')变量仅对应于最近.change()个事件的图层?

5 个答案:

答案 0 :(得分:0)

问题是,每次点击复选框时,都会通过legendFunction注册Leaflet Event回调。因此,每次单击地图时,Leaflet都会使用用于注册回调的lyrs值执行回调。

您可能只想注册一个click事件处理程序。像这样:

HTML:

<div id="layer1" class="layers">
  <input type="checkbox" id="layer1" />
  <label>layer1</label>
</div>

<div id="layer1" class="layers">
  <input type="checkbox" id="layer2" />
  <label>layer2</label>
</div>

<div id="mapid"></div>

JavaScript的:

var mymap = L.map('mapid').setView([51.505, -0.09], 8);

mymap.on('click', function() {
  $(".layers input[type='checkbox']:checked").each(function() {
    console.info(this.id, 'is checked');
  });
});

答案 1 :(得分:0)

您的legendFunction为地图添加了一个事件处理程序(它没有显示但我假设map中的legendFunction是一个表示实际地图的jQuery对象)。问题是它每次运行该函数时都会添加一个新的事件处理程序。 From the jQuery documentation

  

从jQuery 1.4开始,同一个事件处理程序可以多次绑定到一个元素。

当触发该事件时,所有这些重复的处理程序都会触发。每次单击复选框时,都会触发复选框更改处理程序,然后调用legendFunction,这会向地图添加新的单击处理程序。

迭代1

第一次,lyrs被设置为已选中复选框的jQuery对象,它将在控制台上列出。对于map的点击没有事件处理程序(除非legendFunction()在其他地方也被触发,或者如果你在其他地方添加另一个点击处理程序),那么legendFunction(或者更确切地说) legendFunction添加的事件处理程序这次不会生成任何控制台输出。此迭代添加了第一个map单击事件处理程序。

迭代2

下次单击一个复选框时,您将再次从复选框更改处理程序中获取正确的lyrs登录到控制台。您还没有对其进行描述,但如果您的{{1>}上的复选框实际上是 ,则相同的点击会从复选框冒出来map,然后触发map也在迭代1中添加了单击处理程序。根据您的HTML结构,map已经使用新的复选复选框进行更新,迭代1 lyrs点击处理程序的输出将反映出来。此外,此次点击会调用map,并会添加第二个重复的legendFunction()点击事件处理程序。

迭代3

如上所述,除了现在激发2个相同的map点击处理程序,每个处理程序在控制台上生成输出。添加了第三个重复的map点击事件处理程序。

......等

我不知道目标到底是什么,但为了避免这个问题,只需创建一次map点击事件处理程序:

map

答案 2 :(得分:0)

您多次重新绑定点击事件。尝试只输出lyrs的值,而不是再次在legendFunction中绑定点击。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="collapse navbar-collapse" id="myNavbar">
				<ul class="nav navbar-nav top-nav pull-right">
					<div class="dropdown">
						<li class="dropbtn"><a href="#"><i class="fa fa-chevron-down" aria-hidden="true"></i> About Us</a></li>
						<div class="dropdown-content">
							<a href="https://www.yahoo.com/">Action</a>
							<a href="#">Another action</a>
							<a href="#">Something else here</a>
							<a href="#">Separated link</a>
							<a href="#">One more separated link</a>
						</div>
					</div>

					<div class="dropdown">
						<li class="dropbtn"><a href="#"><i class="fa fa-chevron-down" aria-hidden="true"></i> Providers</a></li>
						<div class="dropdown-content">
							<a href="#">Action</a>
							<a href="#">Another action</a>
							<a href="#">Something else here</a>
							<a href="#">Separated link</a>
							<a href="#">One more separated link</a>
						</div>
					</div>

					<div class="dropdown">
						<li class="dropbtn"><a href="#"><i class="fa fa-chevron-down" aria-hidden="true"></i> Payors</a></li>
						<div class="dropdown-content">
							<a href="#">Action</a>
							<a href="#">Another action</a>
							<a href="#">Something else here</a>
							<a href="#">Separated link</a>
							<a href="#">One more separated link</a>
						</div>
					</div>

					<div class="dropdown">
						<li class="dropbtn"><a href="#"><i class="fa fa-chevron-down" aria-hidden="true"></i> Employers</a></li>
						<div class="dropdown-content">
							<a href="#">Action</a>
							<a href="#">Another action</a>
							<a href="#">Something else here</a>
							<a href="#">Separated link</a>
							<a href="#">One more separated link</a>
						</div>
					</div>


					<div class="dropdown">
						<li class="dropbtn"><a href="#"><i class="fa fa-chevron-down" aria-hidden="true"></i> Patients</a></li>
						<div class="dropdown-content">
							<a href="#">Action</a>
							<a href="#">Another action</a>
							<a href="#">Something else here</a>
							<a href="#">Separated link</a>
							<a href="#">One more separated link</a>
						</div>
					</div>
				</ul>
			</div>

答案 3 :(得分:0)

jquery的

on方法会向事件队列添加一个事件监听器,也就是说,如果你调用on方法五次,它会向事件队列添加五个事件监听器。所以,它触发click事件时,将调用事件回调五次,在使用on方法绑定事件监听器之前,应取消所有事件监听器。

&#13;
&#13;
var lyrs;

$("div#myID input:checkbox").change(function() {
    lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
    console.log('in .change(): ', lyrs)
    legendFunction( lyrs );

});

function legendFunction( lyrs ) {
    map.off('click')
    map.on('click', function() {
        console.log('in legendFunction: ', lyrs);
    });
};
&#13;
&#13;
&#13;

答案 4 :(得分:0)

这是因为每次调用map时,您都会将侦听器绑定到legendFunction的点击事件。这是因为每次调用该函数时,都会将lyrs数组作为参数传递(与脚本顶部定义的lyrs变量不同),然后执行绑定,因此您正在创建一个闭包,该闭包会记住该数组在该时间以及随后每次调用该函数时的值。

你的程序基本上是这样做的:

您选中了标识为landfireEVT

的复选框
  • 在更改回调中,您将拥有lyrs = ['landfireEVT']
  • 当您致电legendFunction时,您会向map元素添加新的绑定,并且它会记住&#34; lyrs = [landfireEVT]
  • 如果您点击map元素,刚刚绑定的事件将会触发,在控制台中您会看到lyrs = ['landfireEVT']
  • 的值

现在有人选中了标识为agc

的复选框
  • 在更改回调中,您将拥有lyrs = ['landfireEVT','agc']
  • 当您致电legendFunction时,您会向map元素添加新的绑定,并且它会记住&#34; lyrs = ['landfireEVT','agc']
    • 如果您单击map元素,之前绑定到click事件的第一个回调将会触发,您将在控制台lyrs = ['landfireEVT']中看到,之后第二个回调刚刚绑定到点击事件的内容将会触发,您将看到lyrs = ['landfireEVT','agc']
    • 的值

我只将事件绑定一次并将更新的复选框列表保存在lyrs变量

var lyrs;
map.on('click', function() {
   //lyrs will always be the variable defined above anytime somebody clicks on the map element.
   console.log('in legendFunction: ', lyrs);
 });

$("div#myID input:checkbox").change(function() {
  lyrs = $("div#myID input[type='checkbox']:checked").map(function() { return this.id });
  //add here any other logic you need to notify somebody else that a checkbox changed.
});

您可以在此处了解有关闭包和范围的更多信息https://community.risingstack.com/explaining-javascript-closure-scope-chain-examples/