如何在多个变更事件上使用jQuery Promise [英] How to use jQuery promise on multiple change events

查看:80
本文介绍了如何在多个变更事件上使用jQuery Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,该代码使用基本的选项链父/子关系显示和隐藏选择菜单.进行更改后,我需要调用一个函数.

I've got the following code which shows and hides select menus using a basic options chain parent/child relationship. Once there is a change I need to call a function.

目前,我正在按照以下说明进行操作,每个<select>的更改都会触发一个事件,然后调用该函数.在现实生活中,这是一个ajax调用,但这与问题无关.

Currently I am doing it as demonstrated below, triggering an event on change for each <select>, which then calls the function. In real life this is an ajax call but that is irrelevant to the question.

我下面的代码有效.我要解决的问题是我如何不依赖更改事件就能完成此操作,因为它不必要地多次触发该函数.我只想在更改父对象时将函数调用放在$.each()循环的末尾,但是由于涉及到动画,由于有问题的元素有时仍然可见/隐藏,因此它将失败.我通过在每个slideUp()slideDown()内放置一个回调来解决此问题,但这正是我最终多次触发事件的确切原因.

The code I have below works. The problem I would like to solve is how I can accomplish this without relying on a change event since it triggers the function multiple times unnecessarily. I'd like to simply place a function call at the end of the $.each() loop when the parent is changed but because of the animation involved it will fail since the elements in question are sometimes still visible/hidden. I solved this by placing a callback inside each slideUp() and slideDown() but this is the exact reason I end up triggering things multiple times.

我强烈希望找到的答案使用jQuery promise(),其中指出:

I have a strong feeling that the answer I am looking for uses jQuery promise() which states:

.promise()方法返回一个动态生成的Promise,一旦绑定到该集合的某种类型的所有操作(无论是否排队)都已解决,则该Promise将得到解决.

The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.

这正是我想要做的,但是我对promise()完全困惑,这是正确的用法.我理解了这个概念,但是我可以使用一些帮助来理解如何将所有更改事件排队到一个promise()中,然后在它们全部完成后调用我的函数.

That is exactly what I want to do but I am utterly confused by promise() and it's proper usage. I get the concept, but I could use some help understanding how I can queue all those change events into one promise() and then call my function when they are all complete.

$('select[data-parent="true"]').change(function() {
  var parentValue = +this.value;
  var parentId = $(this).data('parent_id');
  $('div[data-parent_id="' + parentId + '"]').each(function() {
    var parentValues = $(this).data('parent_values');
    if (parentValues.indexOf(parentValue) !== -1) {
      $(this).slideDown(1000, function() {
        $(this).find('select').change();
      });
    } else {
      $(this).slideUp(1000, function() {
        $(this).find('select').change();
      });
    }
  });
});
$('select').on('change', function() {
  var results = '';
  $('div.option').each(function() {
    results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>';
  });
  $('#results').html(results);
});

div {
  padding: 5px 10px;
}

div.child {
  display: none
}

select {
  width: 200px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="option">
  <select name="container" data-parent="true" data-parent_id="10">
  <option value="">--- Select a container---</option>
		<option value="1">Box</option>
		<option value="2">Bag</option>
		<option value="3">Pallet</option>
	</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
  <select name="box color">
		<option value="100">Red</option>
		<option value="200">Blue</option>
	</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
  <select name="bag color">
		<option value="300">Green</option>
		<option value="400">Yellow</option>
	</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
  <select name="pallet color">
		<option value="500">Black</option>
		<option value="600">Yellow</option>
	</select>
</div>
<div id="results">
</div>

推荐答案

由于jQuery动画可以返回诺言.promise()并使用.map而不是.each-代码可以很简单:

As jQuery animations can return promises .promise() and using .map instead of .each - the code can be simply:

$('select[data-parent="true"]').change(function() {
    var parentValue = +this.value;
    var parentId = $(this).data('parent_id');
    $.when.apply($, $('div[data-parent_id="' + parentId + '"]').map(function(i, v) {
        var parentValues = $(this).data('parent_values');
        if (parentValues.indexOf(parentValue) !== -1) {
            return $(this).slideDown(1000).promise();
        } else {
            return $(this).slideUp(1000).promise();
        }
    })).done(function() {
        var results = '';
        $('div.option').each(function() {
            results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>';
        });
        $('#results').html(results);
    });
});

div {
  padding: 5px 10px;
}

div.child {
  display: none
}

select {
  width: 200px;
  margin: 4px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="option">
  <select name="container" data-parent="true" data-parent_id="10">
  <option value="">--- Select a container---</option>
		<option value="1">Box</option>
		<option value="2">Bag</option>
		<option value="3">Pallet</option>
	</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
  <select name="box color">
		<option value="100">Red</option>
		<option value="200">Blue</option>
	</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
  <select name="bag color">
		<option value="300">Green</option>
		<option value="400">Yellow</option>
	</select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
  <select name="pallet color">
		<option value="500">Black</option>
		<option value="600">Yellow</option>
	</select>
</div>
<div id="results">
</div>

这篇关于如何在多个变更事件上使用jQuery Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆