处理过程

上篇我们提到了“剪裁”,本篇我们先来实际体验一下被剪裁掉的页面是如何的,这方便我们对接下来的页面请求过程有一个感性的认识。
假设我的index.php首页是这个结构:头部、主题、侧栏、底部 四大结构组成。

<?php  get_header(); ?>

<div id="container">
</div>

<?php get_sidebar(); ?>

<?php get_footer(); ?>

现在我先把头部剪掉

<?php if( $_GET['ajx'] != 'container' ) { ?>
<?php  get_header(); ?>
<?php } ?>

<div id="container">
</div>

<?php get_sidebar(); ?>

<?php get_footer(); ?>

可以看到我用第一篇中所说的代码将头部包住了,这意味着我把头部剪掉了。
原本首页是 http://127.0.0.1/ ,现在我们以这样的链接形式来访问首页 http://127.0.0.1/?ajx=container
打开这个链接你会发现,首页的头部不见了,由于头部加载了css,你首页的样式也会消失,这个状态就是我们想要ajax请求的,我们不需要头部,把它给剪掉了,接着我们可以用同样的方法剪掉侧栏和底部,最后就会只剩下主体部分,如下:

<?php if( $_GET['ajx'] != 'container' ) { ?>
<?php  get_header(); ?>
<?php } ?>

<div id="container">
</div>

<?php if( $_GET['ajx'] != 'container' ) { ?>
<?php get_sidebar(); ?>
<?php } ?>

<?php if( $_GET['ajx'] != 'container' ) { ?>
<?php get_footer(); ?>
<?php } ?>

这就是真正需要ajax请求的页面了。
我们需要把http://127.0.0.1/?ajx=container 这样的链接传递给ajax方法进行异步请求,
比如在页面A http://127.0.0.1/page-a 中要请求页面B,页面A中的a标签中指向页面B的链接就应该是这样的 http://127.0.0.1/page-b?ajx=container
利用两个js函数来对点击的链接进行处理,加上后面的?=ajx=container参数,在必要的时候后再去掉它们。

完整的PJAX代码

var ajx_content = "#ajx_content";

function rerun() {}

$(function() {
    rerun();
    a();
});

function show_loading(e) {
    if ($("#loading_box").length == 0) {
        var div = "<div id='loading_box'></div><div id='loading'></div><div id='loading-text'></div></div>";
    }
    if (e === true) {
        $("body").append(div);
    } else {
        $("#loading_box,#loading,#loading-text").fadeOut(400, function() {
            $(this).remove();
        });
    }
}

function body_am(id) {
    id = isNaN(id) ? $("#" + id).offset().top : id;
    $("body,html").animate({
        scrollTop: id
    }, 600);
    return false;
}

function pluginRerun() {
    var plugin_scripts = $('script[src*="plugins"]');
    plugin_scripts.each(function() {
        var url = $(this).attr("src");
        $.getScript(url);
    });
}

function addUrlPara(url, para) {
    var strArray = new Array();
    strArray = url.split("?");
    if (strArray.length == 1) {
        if (url.indexOf("#") != -1) {
            strArray = url.split("#");
            return strArray[0] + "?" + para + "#" + strArray[1];
        }
        return url + "?" + para;
    } else {
        if (url.indexOf(para) != -1) return url;
        return strArray[0] + "?" + para + "&" + strArray[1];
    }
}

function removeUrlPara(url, para) {
    var strArray = new Array();
    strArray = url.split(para);
    if (strArray.length == 1) {
        strArray = url.split("?" + para);
        return strArray[0];
    } else {
        if (strArray[1].indexOf("&") != -1) {
            strArray = url.split(para + "&");
            return strArray[0] + strArray[1];
        } else {
            strArray = url.split("?" + para);
            return strArray[0] + strArray[1];
        }
    }
}

function l() {
    history.replaceState({
        url: window.document.location.href,
        title: window.document.title,
        html: $(document).find(ajx_content).html()
    }, window.document.title, document.location.href);
}

function a() {
    window.addEventListener("popstate", function(e) {
        if (e.state) {
            document.title = e.state.title;
            $(ajx_content).html(e.state.html);
            rerun();
        }
    });
}

function ajax(reqUrl, msg, data) {
    if (msg == "pagelink" || msg == "search") {
        show_loading(true);
        $(ajx_content).fadeTo("normal", 0);
        $("body,html").animate({
            scrollTop: $("body").offset().top
        }, 810);
        var paraUrl = addUrlPara(reqUrl, "ajx=container");
    } else if (msg == "comtpagenav") {
        to_anchor("#post-comment-list", 0);
        $("#comment_list").fadeTo(500, .2, function() {
            $("#comment_list").css("position", "relative");
        });
        reqUrl = removeUrlPara(reqUrl, "ajx=container");
        paraUrl = addUrlPara(reqUrl, "ajx=comts");
    }
    $.ajax({
        url: paraUrl,
        data: data,
        beforeSend: function() {
            l();
        },
        success: function(data) {
            if (msg == "pagelink" || msg == "search") {
                $(ajx_content).replaceWith($(data).filter(ajx_content));
                $(ajx_content).fadeTo(500, 1, function() {
                    rerun();
                });
                show_loading(false);
            } else if (msg == "comtpagenav") {
                var content = $(data).find("#comment_list").html();
                $("#comment_list").animate({
                    opacity: 0,
                    top: 35
                }, 200, function() {
                    $("#comment_list").html(content);
                    $("#comment_list").animate({
                        opacity: 1,
                        top: 0
                    }, 400, function() {
                        $("#comment_list").css("position", "inherit");
                    });
                    rerun();
                });
            }
            document.title = $(data).filter("title").text();
            reqUrl = removeUrlPara(reqUrl, "ajx=comts");
            var state = {
                url: reqUrl,
                title: $(data).filter("title").text(),
                html: $(data).filter(ajx_content).html()
            };
            window.history.pushState(state, $(data).filter("title").text(), reqUrl);
        },
        complete: function() {},
        timeout: 5e3,
        error: function(request) {
            if (msg == msg == "pagelink" || msg == "search") {
                show_loading(false);
                location.href = reqUrl;
            } else if (msg == "comtpagenav") {
                $("#comment_list").fadeTo("normal", 1);
                $("#comt_svg").css("display", "none");
                $("#comments_paginate").css("display", "block");
            } else {
                location.href = reqUrl;
            }
        }
    });
}

function check_x(url) {
    var url_string = new String("  , comment-page-, #respond, #comment, javascript:, oauth2, .jpg, .gif, .png");
    var url_x = url_string.split(", ");
    for (var i in url_x) {
        if (url.indexOf(url_x[i]) >= 0) {
            return true;
        }
    }
    return false;
}


$("body").on("click", "a[target!=_blank]:not(.noajx)", function() {
    url = $(this).attr("href");
    if (check_x(url) == true) return;
    ajax(url, "pagelink");
    return false;
});


$("body").on("submit", "#search .s-form", function() {
    ajax(this.action + '?=' + $(this).find("#s").val(), 'search', $(this).serialize());
    return false;
});

$("body").on("click", "#comments_paginate a", function() {
    ajax($(this).attr("href"), "comtpagenav");
    return false;
});

核心就是ajax(reqUrl, msg, data)函数了,还有两个函数需要说明一下
1、check_x(url)函数 —— 这是检查a标签的链接中是否有需要排除的字符,有时候某些a标签是不需要ajax请求的,比如/wp-login.php,图片链接带有.jpg、.gif、.png 等等,都不需要ajax请求,我们得把它们排除掉,加入到check_x(url)内的排除列表内。

2、rerun()函数 —— 这个函数方便我们对其他js脚本进行重新加载,相当于一个回调函数,比如有的站用了多说评论系统,ajax请求时是不会请求css和js的,只抓取html结构,所以ajax加载后多说需要的js就不会一起加过来,这时候就需要把多说的js放进rerun()函数进行重新加载。


好了,PJAX教程就介绍到这里,适合有一定js基础的朋友看,如果连js都不懂,那只能靠百度了。