进度条在 AJAX 表单输出中不起作用 [已关闭]

问题描述 投票:0回答:3

我有一个简单的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>";
?>
javascript php ajax
3个回答
0
投票

您在

setTimeout(function() {
的顶层有
<script>

这意味着它会在解析脚本元素时触发

几秒钟后,所有超时均已到期,该代码已完成。

一段时间后,用户单击提交按钮,该按钮会触发 Ajax 代码,将

.progress
元素添加到页面并使其淡入:

$('.done').html( resultHtml ).fadeIn('slow');

如果您想要修改该 HTML 的代码运行然后,您必须将其放在那里


0
投票

您的进度条在 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;
});

如果第二个例子太难理解,请不要担心。专注于让代码正常工作,并尽量留意代码重复。每次重复大量代码时,可能有更好的方法来完成它。 :)


0
投票
  1. 我建议使用preventDefault()来阻止表单提交而不是返回false。如果在返回 false 之前出现错误,那么表单也会提交

    $('#checkaddress').on('submit', function(e) { 
      e.preventDefault(); // stop the submission
      progress(0); /* my code */`
      /* rest of your code */
    
  2. 您的进度条从 60% 开始

  3. 提交时需要调用进度条

  4. 这是一个非常干燥(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>

© www.soinside.com 2019 - 2024. All rights reserved.