我目前正在处理一组代码,每次发生某个ajax调用时都会运行。
为了做到这一点,我使用下面的代码片段(因为我认为没有html或css,所以错误,但是我只是想显示我的代码,这是正常的):
$(document).ajaxStart(function() {
if ($('.spinner').length < 1) { //as there is no ajaxStop, this makes sure there is not already a spinner
$('body').prepend('<div class="spinner" title="Spinner stuck? Click to remove!"></div>');
}
$('body div').not('.spinner').css('opacity', '0.5'); //this is potentially unnecessary
});
//the rest of the ajax call is not included - just the .done()
.done(function(xhr) {
$('body div').not('.spinner').css('opacity', '0');
$('body').one('transitionend', function(e) {
$('body div').not('.spinner').remove();
$('body').append(xhr);
$('body div').not('.spinner').css('opacity', '0.1');
$('body').one('transitionend', function(e) {
$('body div').css('opacity', '1');
$('.spinner').remove();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
正如您所看到的,我嵌套了.one('transitionend')
,我试图弄清楚它是否正确(作为注释:该代码用于处理登录和注销ajax调用对于我的登录ajax调用,它大部分时间工作但是当前没有用于注销ajax调用 - 我认为它没有注册结束$('body div').not('.spinner').css('opacity', '0.1');
的转换,因为这就是冻结的地方。)
我把this jsfiddle放在了一起。它只是测试嵌套与未声明的事件处理程序。
它们(嵌套和无效)似乎工作原理相同(如果你点击其中一个太多次就会冻结它们 - 它发生在嵌套和未嵌入的情况下 - 但这似乎是在我添加了记录位 - $('#log span').text($('#div1').text());
等。)。
以下是片段中的jsfiddle:
var newCss = {
backgroundColor: 'blue',
width: '25%',
color: 'white'
};
var disabled = false;
$(document).on('click', '#div1', function(e) {
if (disabled) return;
notNested($(this));
});
$(document).on('click', '#div8', function(e) {
if (disabled) return;
nested($(this));
});
function notNested($this) {
disabled = true;
$this.css(newCss);
$('#log span').text($('#div1').text());
$('#div1').one('transitionend', function() {
$('#div2').css(newCss);
$('#log span').text($('#div2').text());
});
$('#div2').one('transitionend', function() {
$('#div3').css(newCss);
$('#log span').text($('#div3').text());
});
$('#div3').one('transitionend', function() {
$('#div4').css(newCss);
$('#log span').text($('#div4').text());
});
$('#div4').one('transitionend', function() {
$('#div5').css(newCss);
$('#log span').text($('#div5').text());
});
$('#div5').one('transitionend', function() {
$('#div6').css(newCss);
$('#log span').text($('#div6').text());
});
$('#div6').one('transitionend', function() {
$('#div7').css(newCss);
$('#log span').text($('#div7').text());
});
$('#div7').one('transitionend', function() {
$('div').removeAttr('style');
$('#log span').text('');
disabled = false;
});
}
function nested($this) {
disabled = true;
$this.css(newCss);
$('#log span').text($('#div8').text());
$('#div8').one('transitionend', function() {
$('#div9').css(newCss);
$('#log span').text($('#div9').text());
$('#div9').one('transitionend', function() {
$('#div10').css(newCss);
$('#log span').text($('#div10').text());
$('#div10').one('transitionend', function() {
$('#div11').css(newCss);
$('#log span').text($('#div11').text());
$('#div11').one('transitionend', function() {
$('#div12').css(newCss);
$('#log span').text($('#div12').text());
$('#div12').one('transitionend', function() {
$('#div13').css(newCss);
$('#log span').text($('#div13').text());
$('#div13').one('transitionend', function() {
$('#div14').css(newCss);
$('#log span').text($('#div14').text());
$('#div14').one('transitionend', function() {
$('#log span').text('');
$('div').removeAttr('style');
disabled = false;
});
});
});
});
});
});
});
}
body {
display: flex;
align-items: flex-start;
/* Can't remember if flex-start is default anyways*/
}
div {
display: inline-block;
width: 25%;
}
div > div {
border: 4px dotted red;
transition: .25s;
display: block;
width: 10%;
padding: 4px 8px;
margin: 16px 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
<div id="div6">6</div>
<div id="div7">7</div>
</div>
<div id="log">We got to: <span></span>
</div>
<div>
<div id="div8">8</div>
<div id="div9">9</div>
<div id="div10">10</div>
<div id="div11">11</div>
<div id="div12">12</div>
<div id="div13">13</div>
<div id="div14">14</div>
</div>
因此,我试图找出哪一个更好用?这对代码/浏览器造成的问题较少?等等。是否有更好的方法来控制依赖于转换(或动画的动作)处于特定状态的代码? (寻找事实答案,而不是意见, TUVM)
我曾尝试过研究jQuery的.queue和.delay,但无法在我的场景中工作(可能是我使用它们错了)。也许这是另一种可能性?我也知道setTimeout()
是可能的,但要保持同步,你需要在它之后嵌套元素(并且.one('transitionend')
似乎在大多数情况下工作 无论你是否嵌套......)
根据此问题留下的以下评论:
关于代码的一些小指针,不要在Jquery中执行css,而是使用不透明度值追加/前置类。使用变量而不是使用每个选择器遍历DOM。 - Jan_dh
我更新了jsfiddle以更改类而不是直接更改CSS。 Here是链接(同样,上面的jsfiddle链接已更新)。
虽然,我不重复的意思是:
使用变量而不是通过每个选择器遍历DOM。
如果这可能是我的问题的答案,也许有人明白他的意思可以在下面阐述?
答案 0 :(得分:2)
您可以使用.queue()
,$.map()
; .one("transitionend")
附加到当前转换元素,处理程序设置为next
,以便在当前元素transition
完成时调用队列中的下一个函数;单个事件处理程序,用于.slice()
将元素id
以"div"
开头的所有元素拆分为数组的两个或多个元素;将数组作为event.data
传递给事件处理程序;使用$.grep()
,.filter()
过滤特定列;将元素集合.data(/* name */)
设置为true
或false
,以防止当转换正在进行时元素当前正在元素click
的队列中转换时转换效果的默认操作;当前队列完成时.promise()
,.then()
执行任务
var newCss = {
backgroundColor: "blue",
width: "25%",
color: "white"
}
// define `log` variable as `"#log span"`
, log = $("#log span")
// define `divs` variable as all elements where `id` begins with`` "div"
, divs = $("[id^=div]")
// define `col1` variable as `divs` at indexes `0` through `7`
, col1 = divs.slice(0, 7)
// define `col2` variable as `divs` at indexes `7` through `div.length`
, col2 = divs.slice(7, divs.length);
function queueColumn(col, name) {
// set current collection of elements `.data("active")` to `true`
return col.data("active", true)
// set a queue name with `name`, call `$.map()` on current collection
.queue(name, $.map(col, function(div) {
// return a function at queue `name` for each element in collection
return function(next) {
// set `log` text
log.text(
// pass reference of `next` function in queue `name`
// as handler for `transitionend` event of current element;
// call `next` function in queue `name`
// at `transitionend` event of element
$(div).one("transitionend", next).css(newCss).text()
)
}
// call first function in queue;
// when all function in queue `name` complete,
// return queue `name` jQuery promise object
})).dequeue(name).promise(name)
}
// handle `click` event at `#div1`, `#div8` elements
function handleQueue(e) {
// define `curr` variable;
// filter array containing `col1`, `col2` collections
// to match collection containing `#div1` or `#div8`
var curr = $.grep(e.data, function(col) {
return col.filter(e.target).length
}).pop();
// create `name` for queue
var name = `col${$.inArray(curr, e.data) + 1}-${$.now()}`;
// check if `curr` `.data("active")` is `undefined`
// at first click of element, if true,
// set `curr` `.data("active")` to `false`
if (curr.data("active") === undefined) {
curr.data("active", false);
}
if (curr.data("name") === undefined) {
curr.data("name", name);
}
console.log(`queue ${curr.data("name")} is active:`
, `${!curr.queue(name).length
|| curr.data("active")}`);
// define `inprogress` as `curr.data().active`
var inprogress = curr.data().active;
// check if `inprogress` is `false`, if true, call call `queueColumn`
// with `curr`, `name` as parameters
// if `#div1` or `#div8` element are clicked during
// during queue, while `inprogress` is `true`,
// return `false` from event handler to prevent
// multiple queues to be set at `curr` at same time
return !inprogress
? queueColumn(curr, name)
// do stuff when current queue `name` completes
// calling all functions in queue array
.then(function() {
console.log(`${this.data("name")} queue complete`);
// remove element `style`, reset `.data()`
this.removeAttr("style")
.data({"active": false, "name": void 0});
})
// else return `false`
: inprogress
}
// at `click` of `#div1`, `#div8`, call `handleQueue`,
// pass array containing `col1`, `col2` as `event.data`
$("#div1, #div8").click([col1, col2], handleQueue);
&#13;
body {
display: flex;
align-items: flex-start;
/* Can't remember if flex-start is default anyways*/
}
div {
display: inline-block;
width: 25%;
}
div > div {
border: 4px dotted red;
transition: .25s;
display: block;
width: 10%;
padding: 4px 8px;
margin: 16px 0px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js">
</script>
<div>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
<div id="div6">6</div>
<div id="div7">7</div>
</div>
<div id="log">We got to: <span></span>
</div>
<div>
<div id="div8">8</div>
<div id="div9">9</div>
<div id="div10">10</div>
<div id="div11">11</div>
<div id="div12">12</div>
<div id="div13">13</div>
<div id="div14">14</div>
</div>
&#13;