如何用ajax显示页面?

Posted

技术标签:

【中文标题】如何用ajax显示页面?【英文标题】:How to display the page with ajax? 【发布时间】:2019-03-15 19:19:00 【问题描述】:

即使我添加了一个过滤器来对同一页面上的更多行进行分页,我的分页也能正常工作,也就是说通过过滤器我可以显示 10 或 50 行。

我的代码中的一个小缺陷是页面被重新加载,改变了显示的行数,分页按钮也发生了同样的情况。

这是我的代码,一切都在同一个页面上运行index2.php

<div id="wrapper">
    <div class="container">
        <div id="news-header" class="bootgrid-header container-fluid">
            <div class="row">
                <div class="col-sm-12 actionBar">
                    <div class="search-bar">
                        <input type="text" id="myInput" onkeyup="myFunction()" placeholder="What are you looking for?">
                    </div>
                    <div class="actions btn-group">
                        <?php
                            $select_quantity = '';
                            if (isset($_POST['amount_show'])) :
                                $select_quantity = $_POST['amount_show'];
                            endif;
                        ?>
                        <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
                            <select id="amount_show" name="amount_show" onchange="this.form.submit()">
                                <option value="10" <?php if ($select_quantity==10) echo "selected"; ?>>10</option>
                                <option value="25" <?php if ($select_quantity==25) echo "selected"; ?>>25</option>
                                <option value="50" <?php if ($select_quantity==50) echo "selected"; ?>>50</option>
                                <option value="100" <?php if ($select_quantity==100) echo "selected"; ?>>100</option>
                            </select>
                        </form>
                    </div>
                </div>
            </div>
        </div>
        <?php
            if (isset($_GET['page'])) :
                $page = $_GET['page'] ?: '';
            else :
                $page = 1;
            endif;

            if (isset($_POST['amount_show'])) :
                $records_by_page = $_POST['amount_show'];
            else :
                $records_by_page = 10;
            endif;

            $localization_sql = ($page-1) * $records_by_page;

            $sql = "SELECT id,title,description
                    FROM news
                    ORDER BY id DESC LIMIT $localization_sql, $records_by_page";
            $stmt = $con->prepare($sql);
            $stmt->execute();
            $stmt->store_result();
            if ($stmt->num_rows>0) :

            echo '<table id="myTable" class="table table-condensed table-hover table-striped bootgrid-table">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Title</th>
                    <th>Description</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>';

            $stmt->bind_result($id,$title,$description);
            while ($stmt->fetch()) :
                echo '<tr>
                    <td>'.$id.'</td>
                    <td>'.$title.'</td>
                    <td>'.$description.'</td>
                    <td>Edit</td>
                </tr>';
            endwhile;
            echo '</tbody>';
            echo '</table>';
            $stmt->close();


            $sql = "SELECT * FROM news";
            $stmt = $con->prepare($sql);
            $stmt->execute();
            $stmt->store_result();

            $BD_records = $stmt->num_rows;
            $stmt->close();
            $con->close();

            $total_page = ceil($BD_records / $records_by_page);
            $prev = $page - 1;
            $next = $page + 1;
            echo '<div class=pagination>
            <ul class="pagination">';
            if ($prev > 0) :
                echo "<li><a href='index2.php?page=1'><i class='icon-angle-double-arrow'></i></a></li>";
                echo "<li><a href='index2.php?page=$prev'><i class='icon-angle-left'></i></a></li>";
            endif;

            for ($i=1; $i<=$total_page; $i++) :
                if ($page==$i) :
                    echo "<li><a class=active>". $page . "</a></li>";
                else :
                    echo "<li><a href='index2.php?page=$i'>$i</a></li>";
                endif;
            endfor;


            if ($page < $total_page ) :
                echo "<li><a href='index2.php?page=$next'><i class='icon-angle-right'></i></a></li>";
                echo "<li><a href='index2.php?page=$total_page'><i class='icon-angle-double-right'></i></a></li>";
            endif;

            echo '</ul></div>';

            else :
                $stmt->close();
            endif;

        ?>
    </div>
</div>

在网上搜索时,我发现了一个 ajax 代码,但老实说,我没有管理使用 ajax 或 javascript/jquery 代码。

你可以解释如何实现这个ajax代码或者如何避免重新加载页面的小缺陷。

<script type="text/javascript">
$(document).ready(function()   
    $('.pagination li a').on('click', function()
        /*$('.items').html('<div class="loading"><img src="images/loading.gif"  /><br/>Loading...</div>');*/
        $('.items').html('<div class="loading">Loading...</div>');

        var page = $(this).attr('data');        
        var dataString = 'page='+page;

        $.ajax(
            type: "GET",
            url: "ajax.php",
            data: dataString,
            success: function(data) 
                $('.items').fadeIn(2000).html(data);
                $('.pagination li').removeClass('active');
                $('.pagination li a[data="'+page+'"]').parent().addClass('active');

            
        );
        return false;
    );              
);    
</script>

这就是我的代码的工作方式,如下图所示:

【问题讨论】:

那么你真的尝试过ajax 吗?如果有,结果如何?您是如何尝试解决您遇到的任何问题的?如果您没有尝试过,那么请尝试一下。您应该在发布问题之前尝试解决您的任务/问题。 @PatrickQ 你好朋友......我已经按照我找到的示例进行操作,显然在 ajax 中正确添加了所有内容,但我很抱歉朋友,但我不知道我应该删除哪些代码文件 index2.php 添加到文件 ajax.php :( 如果我问错了,请原谅我,我只是原生使用 PHP,我不完全了解 ajax 的使用 :( 【参考方案1】:

Ajax 将在不重新加载页面的情况下更新页面上的信息。我们希望将数据从 HTML 中分离出来,这样我们就可以更改我们看到的数据。如果 PHP 是将数据写入 HTML 的工具,我们就无法做到这一点。所以我建议将 index2.php 分成几个文件。此示例使用 JSON。

收集数据

ajax.php

<?php
$data_rows = array();

for ($i = 0; $i < 1000; $i++) 
    $data_rows[] = array(
        "id" => "id_$i",
        "title" => "title_$i",
        "description" => "description_$i",
    );


echo json_encode($data_rows, JSON_PRETTY_PRINT);

这是一些垃圾数据的例子,我不知道你需要什么数据。这里重要的是创建一个包含您想要的所有信息的关联数组,json_encode() 数组,然后是echo 它。重要的是,这是唯一被回显或打印的东西!如果您在此脚本中打印了其他任何内容,这将不起作用。

编辑:

ajax.php

if (isset($_GET['page'])) :
                $page = $_GET['page'] ?: '';
            else :
                $page = 1;
            endif;

            if (isset($_POST['amount_show'])) :
                $records_by_page = $_POST['amount_show'];
            else :
                $records_by_page = 10;
            endif;

$sql = "SELECT id, title, description
FROM news
ORDER BY id DESC LIMIT $localization_sql, $records_by_page";
$result = $con->query($sql);
$data_rows = array();
while ($row = $result->fetch_assoc()) 
    $data_rows = $row;


echo json_encode($data_rows, JSON_PRETTY_PRINT);

您的原始代码包含此 mysqli 连接,这是我无权访问的数据,因此我无法测试此脚本的功效。但是,这应该会显示您询问的所有数据。

Ajax 与 jQuery

script.js

$(document).ready(function()   
 $.ajax(
            type: "GET",
            url: "ajax.php",
            dataType: "json",
            success: function(data) 
                tableRows = '';
                for (let i = 0; i < data.length; i++) 
                    tableRows += `
                    <tr>
                        <td>$data[i].id</td>
                        <td>$data[i].title</td>
                        <td>$data[i].description</td>
                        <td>Edit<td>
                    </tr>`;
                
                $("#tbody-insert").html(tableRows);
            
    );              
); 

将 ajax 调用的 url 参数设置为传递数据的 php 文件的名称。在我使用 JSON 的示例中,设置 dataType: "json" 很重要。 jQuery 会自动为你解析。在success参数中可以看到,data是我们创建的php数组的名称。我使用了一个简单的 for 循环来创建一堆表格行,然后将它们插入到我用id="tbody-insert" 标记的表格主体中。

呈现数据

index.html

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>
<table id="myTable" class="table table-condensed table-hover table-striped bootgrid-table">
    <thead>
        <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Description</th>
            <th>Action</th>
        </tr>
    </thead>
    <tbody id="tbody-insert">

    </tbody>
</table>

我已经从您的索引页面中删除了所有 PHP,它不是很灵活,并且需要在更新信息之前重新加载整个页面。需要注意的重点是脚本标签,您需要包含 jQuery 并且需要包含 script.js。您还需要有一个我们要插入信息的表体的 id。您可以将您的 ajax 包装在一个函数中,该函数在您每次想要分页时都会被调用,并为不同的页面查询 ajax.php。我不知道您的数据结构,因此无法提供更多帮助。

【讨论】:

FWIW,这个答案中的 JavaScript 是 ES6,所以如果你没有转译或支持旧版浏览器,那么字符串插值将不会产生预期的结果。 @Timpy 朋友。想要的数据都在 index2.php 文件中,也就是说,我没有使用或调用另一个 PHP 文件。分页和数据显示在文件 index2.php 中,所有内容都在该文件中。 @Timpy 很抱歉承认这一点。但我不明白,在我的代码中有通过选择选项以这种方式显示 10、25、50 和 100 行的选项,它会失去有效性......我想哭我不明白......所有 PHP 代码都传递给 ajax 文件 .php 但在 json_encode 中仅打印来自数据库的数据和其他配置作为显示更多行的选项。 @Kary 很抱歉没有更清楚。在 index2.php sn-p 的第 46 行,您正在使用以下语句查询数据库:$stmt = $con-&gt;prepare($sql);。这就是我说的数据。我将更新我的答案以使用该数据。 @Timpy 以这种方式向我显示数据$result = $con-&gt;query($sql); $data_rows = array(); while ($row = $result-&gt;fetch_assoc()) $data_rows[] = $row; 【参考方案2】:

让我们从导致页面重新加载的原因开始:default browser actions。几个 html 元素会导致浏览器离开当前页面。在这种情况下,我们关注的是:

#amount_showform 提交(onchange 函数)通过​​ POST 请求发送新值。 分页器本身(带有a 链接)告诉php 脚本通过GET 请求检索哪些记录。

这两个值都应该传递给 php 脚本,以便它能够返回正确的记录,否则 amount 参数将是 php 脚本中的默认值,即使我们选择了不同的值。为此,我们必须将 amount 变量的传递更改为 GET 请求。

另外,当更改amount 值时,我们将默认为第一页以避免重新计算页码。 由于分页链接因此可以动态更改,因此我不会在 javascript 中处理它们,而是在 php 中处理它们,因为我们已经有一个模板和计算。这将使事情更容易改变。

让我们先解决javascript:

$(document).ready(function() 
    // When we change the value of the select...
    //     evt contains the information about the event: 
    //         element receiving the action, the action itself, etc.

    $('#amount_show').change(function(evt) 
      // Cancel the default browser action
      evt.preventDefault()
      // Get the target url of the form (our php script)
      url = $(this).parent().attr('action')
      // Call the funtion that will be doing the request
      ajaxLoad(url)
    );

    // When we click a pagination link... (Explanation below)
    $('.items').on('click', '.pagination li a', function(evt) 
      evt.preventDefault()
      url = $(this).attr('href')
      ajaxLoad(url)
    );

    // Do the actual request
    function ajaxLoad(url) 
      // How many records do we want to show ?
      query_params = 
        amount_show: $('#amount_show').val()
      ;
      // Show an indication that we are working
      $('.items').html('<div class="loading">Loading...</div>')
      $.ajax(
        type: "GET",
        url: url, // Call php, it will default to page 1 if there's no parameter set
        // When calling a link with a page parameter this will be smart
        // enough to append the variable to the query string correctly
        data: $.param(query_params),
        // Handle the data return. In a perfect world, this is always successful
        success: function(data) 
          // Insert the data in the document.
          $('.items').fadeOut('1000', function()  $(this).html(data) ).fadeIn('1000')
        
      );
    
  );

$('.items').on('click', '.pagination li a', function(evt) 行将delegate event listener 附加到.items 元素,该元素将响应.pagination li a 收到的click 事件。这样做而不是直接附加到元素本身的原因有两个:

减少我们必须循环和附加监听器的元素数量。 处理元素的动态插入。在切换内容时,我们会从文档中删除元素,以及它们的监听器。我们必须在每次页面加载时再次附加它们,否则如果没有附加侦听器,它们将返回默认操作。但由于这个元素不会改变,我们不必这样做。

现在是 php。由于您对使用单个文件感兴趣,所以我只是移动一些东西,但它(大部分)将是您现在所拥有的。注意:我可能误解了您的意思通过将所有内容放在一个页面中。如果这是您从主索引中包含的部分模板,则必须更改链接目标和操作以使表单指向它,调整一些 javascript 选择器,您可以跳过整个 ajax 请求检查。 主要变化:

删除您的 onchange 函数调用。 将POST参数更改为GET参数。 添加.items span 以插入元素,因为它不存在。

使用X-Requested-With header 确定页面加载是ajax 加载还是常规加载。另一种方法是返回一个完整的响应并使用 jQuery 过滤它。

<?php
    if (isset($_GET['page'])) :
        $page = $_GET['page'] ?: '';
    else :
        $page = 1;
    endif;

    if (isset($_GET['amount_show'])) :
        $records_by_page = $_GET['amount_show'];
    else :
        $records_by_page = 10;
    endif;

    $localization_sql = ($page-1) * $records_by_page;

    $sql = "SELECT id,title,description
            FROM news
            ORDER BY id DESC LIMIT $localization_sql, $records_by_page";
    $stmt = $con->prepare($sql);
    $stmt->execute();
    $stmt->store_result();

    if ($stmt->num_rows>0) :

        // Start capturing the output
        ob_start();     
    ?>
    <table id="myTable" class="table table-condensed table-hover table-striped bootgrid-table">
        <thead>
            <tr>
                <th>Id</th>
                <th>Title</th>
                <th>Description</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <?php
                $stmt->bind_result($id,$title,$description);
                while ($stmt->fetch()) :
                    echo '<tr>
                        <td>'.$id.'</td>
                        <td>'.$title.'</td>
                        <td>'.$description.'</td>
                        <td>Edit</td>
                    </tr>';
                endwhile;
                $stmt->close();
            ?>
        </tbody>
    </table>
    <div class=pagination>
    <ul class="pagination">                
            <?php            
              // When requesting an out-of-bounds page, this won't execute resulting in 
              // a blank page with no paginator
              $sql = "SELECT * FROM news";
              $stmt = $con->prepare($sql);
              $stmt->execute();
              $stmt->store_result();

              $BD_records = $stmt->num_rows;
              $stmt->close();
              $con->close();

              $total_page = ceil($BD_records / $records_by_page);
              $prev = $page - 1;
              $next = $page + 1;

              if ($prev > 0) :
                  echo "<li><a href='" . $_SERVER['PHP_SELF'] . "?page=1'><i class='icon-angle-double-arrow'></i></a></li>";
                  echo "<li><a href='" . $_SERVER['PHP_SELF'] . "?page=$prev'><i class='icon-angle-left'></i></a></li>";
              endif;

              for ($i=1; $i<=$total_page; $i++) :
                  if ($page==$i) :
                      echo "<li><a class='page-link active' >". $page . "</a></li>";
                  else :
                      echo "<li><a class='page-link' href='" . $_SERVER['PHP_SELF'] . "?page=$i'>$i</a></li>";
                  endif;
              endfor;

              if ($page < $total_page ) :
                  echo "<li><a class='page-link' href='index2.php?page=$next'><i class='icon-angle-right'></i></a></li>";
                  echo "<li><a class='page-link' href='index2.php?page=$total_page'><i class='icon-angle-double-right'></i></a></li>";
              endif;

              echo '</ul></div>';

              // Get the output into a variable
              $results_table = ob_get_clean();

          else :
              $results_table = "<div>No results found</div>";
              $stmt->close();
          endif;

          if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) :
              // If is an ajax request, output just the result table and exit
              echo $results_table;
              die;
          endif;
          // Print the whole page if its not an ajax request
      ?>
  <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js'/>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js' />
  <link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css' type='text/css' />
  <div id='wrapper'>
    <div class='container'>
      <div id='news-header' class='bootgrid-header container-fluid'>
        <div class='row'>
          <div class='col-sm-12 actionBar'>
            <div class='search-bar'>
              <input type='text' id='myInput' placeholder='What are you looking for?'>
            </div>
            <div class='actions btn-group'>
              <form action=<?php echo htmlspecialchars($_SERVER['PHP_SELF']);?>'>
                <select id='amount_show' name='amount_show'>
                </select>
              </form>
            </div>
          </div>
        </div>
      </div>

      <span class='items'>
        <?php echo $results_table; ?>
      </span>
    </div>
  </div>

为了完整起见,不使用 php 分隔响应的替代方法是通过在 ajax success 回调中执行以下操作来使用 jQuery 过滤响应(淡入淡出省略):

results_table = $(data).find('.items').html()
$('.items').html(results_table)

这会将来自服务器的响应转换为 jQuery 对象,并允许正常应用过滤功能。我们提取我们感兴趣的内容(items 的内容:结果表和分页),然后将其附加到现有页面上的items 容器中。

更新:我发布了一个简化的示例,没有与数据库相关的代码here。我认为从/向编辑器复制和粘贴代码时发生了一些奇怪的事情。

参考文献

DOM events jQuery ajax and helper 函数 PHP output buffering Not receiving X_REQUESTED_WITH request header Fade effects in ajax callback

【讨论】:

嗨@msg 不是朋友...我并不是说我只希望它在一页上,只是说明我的代码当前正在运行并且只在一个文件中工作 index2.php . 我现在测试它,它打印出这些错误:Warning: mysqli_stmt::bind_result(): Couldn't fetch mysqli_stmt in index2.php on line 54 -> $stmt-&gt;bind_result($id,$title,$description); Warning: mysqli_stmt::fetch(): Couldn't fetch mysqli_stmt in index2.php on line 55 -> while ($stmt-&gt;fetch()) : Warning: mysqli_stmt::close(): Couldn't fetch mysqli_stmt in index2.php on line 63 -> $stmt-&gt;close(); 我不明白错误,一切似乎都很好。 朋友一个效率问题,这种方式是最好的选择还是通过json更有效? 错误不再显示。但是我没有看到它在实现的所有东西上都发生了很大变化,当点击页面上的按钮时会重新加载......我认为它会有所不同,for example 我尝试过在不使用第三方插件的情况下以原生方式完成所有事情,实际上我已经做到了,只是缺少了 ajax 的那个小细节。【参考方案3】:

如果即使是纯 html 也有点超出限制,那么开始使用 jquery 和异步调用是没有意义的。在初始代码中,您混合使用 POST 和 GET,只使用一个。

<div id="wrapper">
    <div class="container">
        <div id="news-header" class="bootgrid-header container-fluid">
            <div class="row">
                <div class="col-sm-12 actionBar">
                    <div class="search-bar">
                        <input type="text" id="myInput" onkeyup="myFunction()" placeholder="What are you looking for?">
                    </div>
                    <div class="actions btn-group">
                        <?php
    //getting both - page and record_by_page from GET
                            $records_by_page = isset($_GET['amount_show'])?$_GET['amount_show']:10;
                            $page = isset($_GET['page'])?$_GET['page']:1;
    //put page value into form to send it together with amount_show
                        ?>
                        <form method="get" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
                            <select id="amount_show" name="amount_show" onchange="this.form.submit()">
                                <option value="10" <?php if ($records_by_page==10) echo "selected"; ?>>10</option>
                                <option value="25" <?php if ($records_by_page==25) echo "selected"; ?>>25</option>
                                <option value="50" <?php if ($records_by_page==50) echo "selected"; ?>>50</option>
                                <option value="100" <?php if ($records_by_page==100) echo "selected"; ?>>100</option>
                            </select>
                            <input type="hidden" id="page" name="page" value="<?php echo $page; ?>"></input>
                        </form>
                    </div>
                </div>
            </div>
        </div>
        <?php


            $localization_sql = ($page-1) * $records_by_page;

            $sql = "SELECT id,title,description
                    FROM news
                    ORDER BY id DESC LIMIT $localization_sql, $records_by_page";
            $stmt = $con->prepare($sql);
            $stmt->execute();
            $stmt->store_result();
            if ($stmt->num_rows>0) :

            echo '<table id="myTable" class="table table-condensed table-hover table-striped bootgrid-table">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Title</th>
                    <th>Description</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>';

            $stmt->bind_result($id,$title,$description);
            while ($stmt->fetch()) :
                echo '<tr>
                    <td>'.$id.'</td>
                    <td>'.$title.'</td>
                    <td>'.$description.'</td>
                    <td>Edit</td>
                </tr>';
            endwhile;
            echo '</tbody>';
            echo '</table>';
            $stmt->close();


            $sql = "SELECT * FROM news";
            $stmt = $con->prepare($sql);
            $stmt->execute();
            $stmt->store_result();

            $BD_records = $stmt->num_rows;
            $stmt->close();
            $con->close();

            $total_page = ceil($BD_records / $records_by_page);
            $prev = $page - 1;
            $next = $page + 1;
            echo '<div class=pagination>
            <ul class="pagination">';
//add amount_show to each request
            if ($prev > 0) :
                echo "<li><a href='pagination.php?page=1&amount_show=$records_by_page'><i class='icon-angle-double-arrow'></i></a></li>";
                echo "<li><a href='pagination.php?page=$prev&amount_show=$records_by_page'><i class='icon-angle-left'></i></a></li>";
            endif;

            for ($i=1; $i<=$total_page; $i++) :
                if ($page==$i) :
                    echo "<li><a class=active>". $page . "</a></li>";
                else :
                    echo "<li><a href='pagination.php?page=$i&amount_show=$records_by_page'>$i</a></li>";
                endif;
            endfor;


            if ($page < $total_page ) :
                echo "<li><a href='pagination.php?page=$next&amount_show=$records_by_page'><i class='icon-angle-right'></i></a></li>";
                echo "<li><a href='pagination.php?page=$total_page&amount_show=$records_by_page'><i class='icon-angle-double-right'></i></a></li>";
            endif;

            echo '</ul></div>';

            else :
                $stmt->close();
            endif;

        ?>
    </div>
</div>  

【讨论】:

以上是关于如何用ajax显示页面?的主要内容,如果未能解决你的问题,请参考以下文章

如何用JAVA爬取AJAX加载后的页面

如何用php+ajax实现页面的局部刷新?(转)

如何用ajax实现,刷新页面时,页面设置的下拉菜单(select)、raido保持不变?

如何用jquery $.ajax向aspx页面传递json格式数据

在java Web中如何用Ajax实现用户名已存在

ASP如何用Ajax实现无刷新读取数据库信息(后台发布信息,前台不刷新也能看到)