PJAX实现

一、浏览器历史API

浏览器历史就像一堆卡片,如下所示:

在HTML4中,我们已经可以使用window.history对象来控制历史记录的跳转,可以使用的方法包括:

方法 描述
back() 加载 history 列表中的前一个 URL。
forward() 加载 history 列表中的下一个 URL。
go() 加载 history 列表中的某个具体页面。

HTML5引进了history.pushState()方法和history.replaceState()方法,它们允许你逐条地添加和修改历史记录条目。这些方法可以协同window.onpopstate事件一起工作。

方法 描述
pushState() 有三个参数:一个状态对象、一个标题(现在会被忽略),一个可选的URL地址
replaceState() 操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。
popstate事件 每当激活的历史记录发生变化时,都会触发popstate事件。

如果要做浏览器兼容,可以下载History.js解决。下面做个简单的demo:

<h1 id="number">1</h1>

<a id="forward" href="?num=2">Go Forward</a>
var link = document.getElementById('forward');

var num = document.getElementById('number');

link.addEventListener('click', function(e){

    e.preventDefault();

    var myNum = parseInt(num.innerHTML, 10);

    num.innerHTML = ++myNum;

    history.pushState({count:myNum}, null, '?num='+myNum);

    document.title = 'Number'+myNum;

});

点击按钮的时候,上面的URL在改变,但点击浏览器的后退按钮的时候,上面的内容是不变的。

接下来,我们给popstate加个监听器,监听数字。数字内容也就会随着改变了。

addEventListener('popstate', function(e){

    if(e.state && e.state.count) {

        num.innerHTML = e.state.count;

        document.title = 'Number'+e.state.count;

    }else {

        num.innerHTML = 1;

        document.title = 1;

    }

});

 

二、创建一个路由

PAJX就是pushState+Ajax。同时使用这两者,只需更新页面的一小部分和URL,页面不需要重新加载,这样就能极大加快访问速度。

建立一个单页程序的方法很多,最简单的就是使用一个路由。

var routes = [];

//建立route对象,插入到数组routes中

function addRoute(route, callback, scope) {

    var routeObj = {

        route: route,

        callback: callback,

        scope, scope

    };

    routes.push(routeObj);

}

//匹配符合要求的route,并执行回调函数

function handleRoute(path, noHistory) {

    var len = routes.length, scope;

    for(var i=0; i<len; i++) {

        if(path.match(routes[i].route)) {

            //如果给定了作用域就用给的作用域

            if(routes[i].scope) {

                scope = routes[i].scope;

            }else {

                scope = window;

            }

            //如果是来自popstate事件,就不必再加入到栈中

            if(!noHistory) {

                history.pushState({}, null, path);

            }

            

            routes[i].callback.apply(scope, [path]);

            return true;

        }

    }

    //没有route返回false

    return false;

}

只需添加一个监听器就能让历史记录起作用。

window.addEventListener('popstate', function(e) {

    handleRoute(window.location.href, true);

});

router = {

    handleRoute:handleRoute,

    addRoute:addRoute

};

给页面上的a标签按钮添加事件

//拦截单击,简单的绑定页面上面的a标签的点击事件

document.addEventListener('click', function(e) {

    if(e.target.href) {

        if(router.handleRoute(e.target.href)) {

            e.preventDefault();

        }

    }

});

 

三、添加ajax请求

这里还做了点简单的缓存操作。点击后退按钮页面上的内容还能存在。

//缓存ajax的响应

var pageCache = {};



//格式化链接

function normalizeLink(path) {

    return path.match(/([a-z_]+\.html)/)[1];

}



//执行ajax请求或使用缓存

function handlePage(path) {

    var href = normalizeLink(path);

    if(pageCache[href]) {

        document.querySelector('.content').innerHTML = pageCache[href];

    } else {

        ajax.makeRequest(href.replace('.html', '_frag.html'), function(xhr) {

            document.querySelector('.content').innerHTML = xhr.responseText;

            pageCache[href] = xhr.responseText;



        }, this);

    }    

}



router.addRoute(/[a-z_]+\.html/, handlePage);

 

代码是参照《HTML5触摸界面设计与开发》这本书的示例demo而写的。这本书的源码可以在这里获取到

demo下载:

http://download.csdn.net/detail/loneleaf1/8730963

 

 

参考资料:

http://www.w3school.com.cn/jsref/dom_obj_history.asp History 对象

https://developer.mozilla.org/zh-CN/docs/DOM/Manipulating_the_browser_history 操纵浏览器的历史记录

 

你可能感兴趣的:(实现)