我有一个简单的ajax表单。但进度条不适用于 ajax 表单输出,它会冻结。我在页面上放置了一个示例,以便您可以看到它正常工作。 我的目标是能够在 ajax 输出中提供代码(进度条)。 https://stackoverflow.com/a/35985771/20310847
这里的问题是,我相信检查 AJAX 输出中的进度条的脚本和 ajax 之间存在冲突/冲突。然后它出现,当它完成时,它消失了,但没有视觉进展...我想知道我需要做什么才能使 Ajax 输出的进度条看起来正常而不冻结?
表格.htm
<html>
<head>
<!-- progress bar style start -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.progress,
.alert {margin: 8px;}
.alert {display: none;}
.alert-success {
--bs-alert-color: #2c4238;
--bs-alert-bg: #f8faff;
--bs-alert-border-color: #768478;
width: auto;
max-width: max-content;
}
@media screen and (max-width: 1568px) {
.alert-success {
width: auto;
max-width: max-content;
}
}
</style>
</head>
<!-- progress bar style end -->
<body><br>
<!-- form start -->
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<form class="form" action="process.php" method="POST" name="checkaddress" id="checkaddress">
<input type="text" name="v" /> </td><input type="submit" id="submit" value="Submit" />
</form>
<!-- form end -->
<!-- ajax output div is here -->
<div class="done"></div>
<!-- Here is the progress code I want to reflect in the ajax output. start -->
<br>====================================
<br> Example: normally this code(progress bar) works below. but it doesn't work when I call the code with ajax. freezes as above.
<br>
<div class='progress col-md-7 ps-0 pe-0'>
<div class='progress-bar' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%;'></div>
</div>
<div class='alert alert-success' role='alert'>hello xxxxx</div><br>
<!-- end -->
<!-- form ajax script start -->
<script>
$('#checkaddress').on('submit', function(e) {
// get formdata in a variable that is passed to the ajax request
var dataToPassToAjax = $(this).serialize();
$.ajax({
url: "process.php",
type: "POST",
data: dataToPassToAjax,
cache: false,
success: function(resultHtml) {
// add the returned data to the .done element
$('.done').html(resultHtml).fadeIn('slow');
}
});
// cancel the default form submit
return false;
});
</script>
<!-- end -->
<!-- progress bar script start -->
<script>
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
setTimeout(function() {
$progressBar.css('width', '10%');
setTimeout(function() {
$progressBar.css('width', '30%');
setTimeout(function() {
$progressBar.css('width', '45%');
setTimeout(function() {
$progressBar.css('width', '80%');
setTimeout(function() {
$progressBar.css('width', '90%');
setTimeout(function() {
$progressBar.css('width', '95%');
setTimeout(function() {
$progressBar.css('width', '98%');
setTimeout(function() {
$progressBar.css('width', '99%');
setTimeout(function() {
$progressBar.css('width', '100%');
setTimeout(function() {
$progress.css('display', 'none');
$alert.css('display', 'block');
}, 500); // WAIT 5 milliseconds
}, 500); // WAIT 5 milliseconds
}, 800); // WAIT 5 milliseconds
}, 600); // WAIT 2 seconds
}, 700); // WAIT 1 seconds
}, 900);
}, 600); // WAIT 2 seconds
}, 400); // WAIT 1 seconds
}, 700); // WAIT 1 seconds
}, 800); // WAIT 1 second
</script>
<!-- progress bar script end -->
</body>
</html>
流程.php
<?php
$v= $_POST['v'];
echo "<div class='progress col-md-7 ps-0 pe-0'>
<div class='progress-bar' role='progressbar' aria-valuenow='60' aria-valuemin='0'
aria-valuemax='100' style='width: 60%;'></div>
</div>
<div class='alert alert-success' role='alert'>hello $v</div>";
?>
您在
setTimeout(function() {
的顶层有 <script>
。
这意味着它会在解析脚本元素时触发。
几秒钟后,所有超时均已到期,该代码已完成。
一段时间后,用户单击提交按钮,该按钮会触发 Ajax 代码,将
.progress
元素添加到页面并使其淡入:
$('.done').html( resultHtml ).fadeIn('slow');
如果您想要修改该 HTML 的代码运行然后,您必须将其放在那里。
您的进度条在 AJAX 中不起作用,因为首次加载页面时,没有可以使用的进度条 - 它仅在 AJAX 调用后出现。当页面加载时,进度条脚本会立即运行,并尝试访问尚不存在的
.progress
、.progress-bar
和 .alert
元素,因为它们仅在 AJAX 调用后添加到页面中。
要使其正常工作,您应该将进度条脚本包含到 AJAX 调用的
success
函数中。这样,它将在新元素添加到页面后被调用。
这是修改后的 JavaScript 代码:
$('#checkaddress').on('submit', function(e) {
// get formdata in a variable that is passed to the ajax request
var dataToPassToAjax = $(this).serialize();
$.ajax({
url: "process.php",
type: "POST",
data: dataToPassToAjax,
cache: false,
success: function(resultHtml) {
// add the returned data to the .done element
$('.done').html(resultHtml).fadeIn('slow');
// run the progress bar script here
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
setTimeout(function() {
$progressBar.css('width', '10%');
setTimeout(function() {
$progressBar.css('width', '30%');
setTimeout(function() {
$progressBar.css('width', '45%');
setTimeout(function() {
$progressBar.css('width', '80%');
setTimeout(function() {
$progressBar.css('width', '90%');
setTimeout(function() {
$progressBar.css('width', '95%');
setTimeout(function() {
$progressBar.css('width', '98%');
setTimeout(function() {
$progressBar.css('width', '99%');
setTimeout(function() {
$progressBar.css('width', '100%');
setTimeout(function() {
$progress.css('display', 'none');
$alert.css('display', 'block');
}, 500); // WAIT 5 milliseconds
}, 500); // WAIT 5 milliseconds
}, 800); // WAIT 5 milliseconds
}, 600); // WAIT 2 seconds
}, 700); // WAIT 1 seconds
}, 900);
}, 600); // WAIT 2 seconds
}, 400); // WAIT 1 seconds
}, 700); // WAIT 1 seconds
}, 800); // WAIT 1 second
}
});
// cancel the default form submit
return false;
});
这应该可以解决您的问题。现在,进度条脚本在 AJAX 调用成功后运行,并且新元素已添加到 DOM,因此它应该能够按预期查找和操作它们。
当前的 JavaScript 代码涉及大量嵌套的
setTimeout
函数,这使得阅读和维护变得困难。我们可以通过更加动态和模块化的方法来简化它。
考虑这样的事情:
$('#checkaddress').on('submit', function(e) {
// get formdata in a variable that is passed to the ajax request
var dataToPassToAjax = $(this).serialize();
$.ajax({
url: "process.php",
type: "POST",
data: dataToPassToAjax,
cache: false,
success: function(resultHtml) {
// add the returned data to the .done element
$('.done').html(resultHtml).fadeIn('slow');
// run the progress bar script here
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
var width = 0;
var increment = 10; // change the increment value to control the speed of the progress bar
var interval = setInterval(function() {
width = width + increment;
if(width >= 100) { // when progress reaches 100, stop interval and show alert
clearInterval(interval);
$progress.css('display', 'none');
$alert.css('display', 'block');
}
$progressBar.css('width', width + '%');
}, 800); // this value controls the delay between each increment
}
});
// cancel the default form submit
return false;
});
这里,进度条宽度每800毫秒增加10%,直到达到100%,此时间隔被清除并显示警报。
这种方法比我推荐的方法稍微不太灵活,但更容易理解。如果你无论如何都想尝试一下,我个人会这样做。
async function delay(duration) {
return new Promise(resolve => setTimeout(resolve, duration));
}
async function updateProgressBar($progressBar, $progress, $alert, values) {
for(let i = 0; i < values.length; i++) {
await delay(values[i].delay);
$progressBar.css('width', `${values[i].width}%`);
}
$progress.css('display', 'none');
$alert.css('display', 'block');
}
$('#checkaddress').on('submit', function(e) {
// get formdata in a variable that is passed to the ajax request
var dataToPassToAjax = $(this).serialize();
$.ajax({
url: "process.php",
type: "POST",
data: dataToPassToAjax,
cache: false,
success: function(resultHtml) {
// add the returned data to the .done element
$('.done').html(resultHtml).fadeIn('slow');
// run the progress bar script here
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
var values = [
{width: 10, delay: 800},
{width: 30, delay: 700},
{width: 45, delay: 400},
{width: 80, delay: 600},
{width: 90, delay: 900},
{width: 95, delay: 700},
{width: 98, delay: 600},
{width: 99, delay: 800},
{width: 100, delay: 500}
];
updateProgressBar($progressBar, $progress, $alert, values);
}
});
// cancel the default form submit
return false;
});
如果第二个例子太难理解,请不要担心。专注于让代码正常工作,并尽量留意代码重复。每次重复大量代码时,可能有更好的方法来完成它。 :)
我建议使用preventDefault()来阻止表单提交而不是返回false。如果在返回 false 之前出现错误,那么表单也会提交
$('#checkaddress').on('submit', function(e) {
e.preventDefault(); // stop the submission
progress(0); /* my code */`
/* rest of your code */
您的进度条从 60% 开始
提交时需要调用进度条
这是一个非常干燥(DRY:不要重复自己)的进度代码
https://jsfiddle.net/mplungjan/r1hsom07/
我还建议您淡入进度条末尾的完成。
let $progress = $('.progress'),
$progressBar = $('.progress-bar'),
$alert = $('.alert'),
steps = [
{ percent: '10%', delay: 800},
{ percent: '30%', delay: 700},
{ percent: '45%', delay: 400},
{ percent: '80%', delay: 600},
{ percent: '90%', delay: 900},
{ percent: '95%', delay: 700},
{ percent: '98%', delay: 600},
{ percent: '99%', delay: 800},
{ percent: '100%', delay: 500},
{ percent: 'none', delay: 500}
];
const progress = i => {
if (i >= steps.length) return;
setTimeout(() => {
if (steps[i].percent === 'none') {
$progress.css('display', 'none');
$alert.css('display', 'block');
} else {
$progressBar.css('width', steps[i].percent);
}
progress(i + 1);
}, steps[i].delay);
}
progress(0); // Start (move this to your ajax)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<div class='progress col-md-7 ps-0 pe-0'>
<div class='progress-bar' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 0%;'></div>
</div>
<div class='alert alert-success' role='alert'>hello xxxxx</div><br>