如何在多个更改事件中使用jQuery承诺
我有下面的代码,它显示并隐藏使用基本选项链父/子关系的选择菜单。一旦有变化,我需要调用一个函数。如何在多个更改事件中使用jQuery承诺
目前我正在按照下面的说明进行操作,每触发一个事件<select>
,然后调用该函数。在现实生活中,这是一个阿贾克斯呼吁,但这与问题无关。
我下面的代码工程。我想要解决的问题是,如何在不依赖更改事件的情况下完成此操作,因为它会不必要地多次触发该功能。我只想简单地在$.each()
循环的末尾放置一个函数调用,当父对象被更改时,但由于涉及动画,它将失败,因为有问题的元素有时仍可见/隐藏。我通过在每个slideUp()
和slideDown()
之间放置一个回调来解决这个问题,但这是我最终触发事件多次的确切原因。
我有我要找的答案用了jQuery promise()
其中规定一个强烈的感觉:
的.promise()方法返回一个动态生成的承诺,解决一旦某种类型绑定的所有行动收集,排队或不,已经结束。
这正是我想要做的,但我完全被promise()
搞糊涂了,它是正确的用法。我明白了,但我可以利用一些帮助理解如何将所有这些更改事件排入一个promise()
,然后在全部完成时调用我的函数。
$('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>
\t \t <option value="1">Box</option>
\t \t <option value="2">Bag</option>
\t \t <option value="3">Pallet</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
<select name="box color">
\t \t <option value="100">Red</option>
\t \t <option value="200">Blue</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
<select name="bag color">
\t \t <option value="300">Green</option>
\t \t <option value="400">Yellow</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
<select name="pallet color">
\t \t <option value="500">Black</option>
\t \t <option value="600">Yellow</option>
\t </select>
</div>
<div id="results">
</div>
在jQuery动画可以返回承诺.promise()
和使用.map
代替.each
- 该代码可以是简单的:
$('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>
\t \t <option value="1">Box</option>
\t \t <option value="2">Bag</option>
\t \t <option value="3">Pallet</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
<select name="box color">
\t \t <option value="100">Red</option>
\t \t <option value="200">Blue</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
<select name="bag color">
\t \t <option value="300">Green</option>
\t \t <option value="400">Yellow</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
<select name="pallet color">
\t \t <option value="500">Black</option>
\t \t <option value="600">Yellow</option>
\t </select>
</div>
<div id="results">
</div>
实验已经产生了以下解决方案的一个小时。创建一个$.Deferred()
对象的数组,并使用$.when
来解决它们。棘手的部分来自this answer,它解释了如何将数组传递给$.when
。希望这可以帮助别人使用jQuery挣扎递延对象,好像我是:
$('select[data-parent="true"]').change(function() {
var deferred = [];
var parentValue = +this.value;
var parentId = $(this).data('parent_id');
$('div[data-parent_id="' + parentId + '"]').each(function(i, v) {
deferred[i] = $.Deferred();
var parentValues = $(this).data('parent_values');
if (parentValues.indexOf(parentValue) !== -1) {
$(this).slideDown(1000, function() {
deferred[i].resolve();
});
} else {
$(this).slideUp(1000, function() {
deferred[i].resolve();
});
}
});
$.when.apply($, deferred).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>
\t \t <option value="1">Box</option>
\t \t <option value="2">Bag</option>
\t \t <option value="3">Pallet</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[1]">
<select name="box color">
\t \t <option value="100">Red</option>
\t \t <option value="200">Blue</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[2]">
<select name="bag color">
\t \t <option value="300">Green</option>
\t \t <option value="400">Yellow</option>
\t </select>
</div>
<div class="child option" data-parent_id="10" data-parent_values="[3]">
<select name="pallet color">
\t \t <option value="500">Black</option>
\t \t <option value="600">Yellow</option>
\t </select>
</div>
<div id="results">
</div>
当然,知道jQuery动画可以“本地”返回承诺 - 并使用.map代替.each - 代码可以进一步简化为https://jsfiddle.net/0ruud9xL/ –
那么这就是最酷的事情我一整天都见过。你应该把它作为另一个答案,我很乐意将它标记为已接受。谢谢! – billynoah
答案补充 - 虽然我没有测试它 - 从头开始测试它现在 –
谢谢 - 我一直是'map()'的粉丝,它是合适的,这比我想出的更优雅和直观我。 – billynoah
我很惊讶关于这个话题的问答在SO上并不常见..我找到了一些好的线索,但没有像我期望的那么多,因为对此的需求可能始终存在。我认为很多人只是满足于它的作品,并不介意20个事件在他们只需要一个事件时就被触发。 – billynoah