如何将Ajax / JQuery应用于现有的PHP MYSQL分页脚本?

4
以下是一个可以从MySQL数据库中显示内容的分页脚本。我需要让页面无缝地加载到"#content"容器中,而不是整个页面都要刷新。我花费了很长时间搜索但没有找到任何教程能帮助我在这个脚本上实现Ajax / JQuery。
下面是用于显示文章和分页的代码。
<div id="content">
<?php
include('db.php');

$stmt = $db->query('SELECT * FROM db');
$numrows = $stmt->rowCount();
$rowsperpage=21;
$totalpages=ceil($numrows/$rowsperpage);

if(isset($pageid)&&is_numeric($pageid)){$page=$pageid;}else{$page=1;} 
if($page>$totalpages){$page = $totalpages;} 
if($page<1){$page=1;}

$offset=($page-1)*$rowsperpage;

$stmt=$db->prepare("SELECT * FROM db ORDER BY ID DESC LIMIT ?,?");
$stmt->bindValue(1, "$offset", PDO::PARAM_STR);
$stmt->bindValue(2, "$rowsperpage", PDO::PARAM_STR);

if($stmt->execute()) {
while ($row = $stmt->fetch()) {
echo '

<article>
article here
</article>

';}}

$range=4;
echo'
<div id="pagination">';

if($page>1){
echo "
<a href='http://www.domain.com/1/'><<</a>";
$prevpage = $page - 1;
echo "
<a href='http://www.domain.com/$prevpage/'><</a>";
}

for ($x = ($page - $range); $x < (($page + $range) + 1); $x++) {
if(($x>0)&&($x<= $totalpages)){
if($x==$page){
echo'
<span class="current">'.$x.'</span>';
}
else{echo"<a href='http://www.domain.com/$x/'>$x</a>";}
}
}

if($page!=$totalpages){
$nextpage=$page+1;
echo"
<a href='http://www.domain.com/$nextpage/'>></a>";
echo "
<a href='http://www.domain.com/$totalpages/'>>></a>";
} 
echo '
</div>';
?>

<a href='http://www.domain.com/1/'><<</a>请在需要输出这些字符时使用&lt;&gt; - Popnoodles
2个回答

3
你的设置有些不太清晰,但请耐心等待。
我假设在客户端上你知道何时加载下一页(即用户单击按钮或滚动到页面末尾等)。我还假设你发布的PHP代码在自己的文件中,并且仅输出你在问题中发布的内容(即它仅输出文章的HTML而没有其他任何内容,没有包装器等;如果没有,请这样做)。
你需要使用jQuery(从你的问题中看来,你已经将其添加到了你的站点上,因此添加另一个库并不太禁忌),向此PHP页面发出AJAX请求。PHP然后会输出你发布的内容,而jQuery则将其插入到页面内部的#content div中。
首先要注意:我不建议让你的PHP页面输出内容div,我建议保留在客户端,只更改其内容以符合你的脚本返回的内容。
为了加载新内容,你可以在客户端上使用以下javascript函数:
function makePaginationRequest( pagenum = 1 ) {
    // Make ajax request
    $.ajax("test2.php", {
        // Data to send to the PHP page
        data: { "pagenum": pagenum },

        // Type of data to receive (html)
        dataType: 'html',

        // What to do if we encounter a problem fetching it
        error: function(xhr, text){
            alert("Whoops! The request for new content failed");
        },

        // What to do when this completes succesfully 
        success: function(pagination) {
            $('#content').html(pagination);
        }
    })
}

您可以将需要传递给服务器的任何其他参数放入“data”对象中(如键值对形式的 data: { "pagenum": pagenum })。从示例中可以看出,您将页面编号传递到此函数中,它将请求变量“pagenum”传递给服务器。
显然,您需要实现更好的错误处理。同时,请将“test2.htm”文件名更改为您的PHP脚本文件名。
更好的方法是:
我感到有必要提及:
上面的方式(您所要求的)实际上是一种混乱的方式。每当您从服务器请求AJAX数据时,服务器应返回内容,而不是标记。然后,您应在客户端将此内容插入标记中。
要做到这一点,您需要修改PHP脚本,先将所有内容放入数组中(或者对于多个文章,放入数组的数组中),如下所示:
while ($row = $stmt->fetch()) {
    $output_array[] = array(
        "post_title" => $row["title"],
        "post_date" => $row["date"],
        // etc....
    );
}

然后像这样回显它:
die(json_encode($output_array));

然后修改你的JSON请求:
function makePaginationRequest( pagenum = 1 ) {
    $.ajax("test2.htm", {
        data: { "pagenum": pagenum },
        dataType: 'json',
        error: function(xhr, text){
            alert("Whoops! The request for new content failed");
        },
        success: function(pagination) {
            // Empty the content area
            $('#content').empty();

            // Insert each item
            for ( var i in pagination ) {
                var div = $('<article></article>');
                div.append('<span class="title">' + pagination[i].post_title + "</span>");
                div.append('<span class="date">' + pagination[i].post_date + "</span>");
                $('#content').append(div)
            }
        }
    })
}

jQuery会自动将此JSON输出解析为本机JavaScript对象。

采用客户端制作标记的方法可以减轻服务器的负担,并减少带宽需求。

这是一个值得思考的建议,希望能对您有所帮助。


1
如果您希望对原始脚本进行最少的重写,那么 jQuery 的 .load() 方法可能是您最好的选择。您只需要向包含所有文章的元素提供一个 id,类似这样的方法应该可以工作:
<div id="container">

    <div id="articles-container">

        <article> ... </article>

    </div>

</div>   

<div id="pagination">
    <a href="some-valid-url">1</a> ...
</div>

然后添加一个 script 标签和一些 jQuery 代码:
<script>

    $(function(){

        $('#pagination').on('click', 'a', function(e){

            e.preventDefault();
            var url = $(this).attr('href');
            $('#container').load(url + ' #articles-container');

        });

    });

</script>

.load()会获取页面,如果您在URL中添加可选片段,则会将结果过滤为与片段匹配的元素。

编辑:

好的,为了使当前的分页工作起来,您需要手动交换元素。因此,假设您生成的标记看起来像这样:

<div id="pagination">
    <a href="/1">1</a>
    <span class="current">2</span>
    <a href="/3">3</a>
    <a href="/4">4</a>
    <a href="/5">5</a>
</div>

我们希望在load()完成后发生这种情况,因此需要向其中添加一个回调函数。我还会添加对点击元素的自我引用,稍后我们需要用到它。
$(function(){

    $('#pagination').on('click', 'a', function(e){

        e.preventDefault();
        var $this = $(this);
        var url = $this.attr('href');
        $('#container').load(url + ' #articles-container', function(response, status, jqxhr){

        });

    });

});

回调函数是我们开始操作#pagination的地方。第一部分很容易:

var $curr = $('#pagination span.current');
var page = $curr.text();

$curr.replaceWith('<a href="/' + page + '">' + page + '</a>');

现在我们需要替换刚刚点击的链接:
$this.replaceWith('<span class="current">' + $this.text() + '</span>');

好了,你的分页应该已经更新了。以下是整个更新过程:

$(function(){

    $('#pagination').on('click', 'a', function(e){

        e.preventDefault();
        var $this = $(this);
        var url = $this.attr('href');
        $('#container').load(url + ' #articles-container', function(response, status, jqxhr){

            var $curr = $('#pagination span.current');
            var page = $curr.text();

            $curr.replaceWith('<a href="/' + page + '">' + page + '</a>');

            $this.replaceWith('<span class="current">' + $this.text() + '</span>');
        });

    });

});

有趣的是,我之前从未听说过.load()函数。干净利落的回答,点赞。 - Mike Blouin
@MikeBlouin 嗯,jQuery API 的新设计使得浏览它不再那么痛苦:http://api.jquery.com/ - 我总是能找到一些比我的原始解决方案更容易的东西... - Tieson T.
这个工作得很好!但是分页链接没有更新。我该如何使分页更新? - user1985705
@user1985705 嗯,这要么需要对上面的示例进行一些级联更改,要么就需要在jQuery中添加和删除适当的标记。你可以试着自己尝试第二个选项,如果你无法实现,我很乐意修改我的答案。 - Tieson T.
我卡住了。我的页眉和页脚出现了重复的副本。 - user1985705

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接