PJAX的基本思路是,用户点击一个连接,经过ajax更新页面变化的部分,而后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的从新加载。若是浏览器不支持history的两个新API或者JS被禁用了,那这个连接就只能跳转并从新刷新整个页面了。和传统的ajax设计稍微不一样,ajax一般是从后台获取JSON数据,而后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片.css
客户端向服务器发送一个普通的请求(1),其实也就是点击了一个连接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。可是这两次请求都让客户端的URL变化了,但愿上面的说明可让你明白了PAJX和AJAX的区别了。html
/** * 方式一 按钮父节点监听事件 * * @param selector 触发点击事件的按钮 * @param container 展现刷新内容的容器,也就是会被替换的部分 * @param options 参数 */ $(document).pjax(selector, [container], options); // 方式二 直接对按钮监听,能够不用指定容器,使用按钮的data-pjax属性值查找容器 $("a[data-pjax]").pjax(); // 方式三 常规的点击事件监听方式 $(document).on('click', 'a', $.pjax.click); $(document).on('click', 'a', function(event) { var container = $(this).closest('[data-pjax-container]'); $.pjax.click(event, container); }); // 下列是源码中介绍的其余用法,因为本人暂时没有那些需求暂时没深究,有兴趣的各位本身试试看哈 // 表单提交 $(document).on('submit', 'form', function(event) { var container = $(this).closest('[data-pjax-container]'); $.pjax.submit(event, container); }); // 加载内容到指定容器 $.pjax({ url: this.href, container: '#main' }); // 从新当前页面容器的内容 $.pjax.reload('#container');
参数名 | 默认值 | 说明 |
---|---|---|
timeout | 650 | ajax 超时时间(单位ms),超时后会执行默认的页面跳转,因此超时时间不该太短,不过通常不须要设置 |
push | true | 使用window.history.pushState改变地址栏url(会添加新的历史记录) |
replace | false | 使用window.history.replaceState改变地址栏url(不会添加历史记录) |
maxCacheLength | 20 | 缓存的历史页面个数(pjax加载新页面前会把原页面的内容缓存起来,缓存加载后其中的脚本会再次执行) |
version | 是一个函数,返回当前页面的pjax-version,即页面中<meta http-equiv="x-pjax-version">标签内容。使用response.setHeader("X-PJAX-Version", "") 设置与当前页面不一样的版本号,可强制页面跳转而不是局部刷新。 |
|
scrollTo | 0 | 页面加载后垂直滚动距离(与原页面保持一致可以使过分效果更平滑) |
type | "GET" | ajax的参数,http请求方式 |
dataType | "html" | ajax的参数,响应内容的Content-Type |
container | 用于查找容器的CSS选择器,[container]参数没有指定时使用 | |
url | link.href | 要跳转的链接,默认a标签的href属性 |
target | link | pjax事件参数e的relatedTarget属性,默认为点击的a标签 |
fragment | 使用响应内容的指定部分(css选择器)填充页面,服务端不进行处理致使全页面请求的时候须要使用该参数,简单的说就是对请求到的页面作截取 |
会有一些状况致使pjax失效,下面结合源码分析下(省略部分无关代码)前端
function handleClick(event, container, options) { ... // 1. 点击事件的事件源不是a标签。使用a标签能够作到对旧版本浏览器的兼容,因此不建议使用其余标签注册事件 if (link.tagName.toUpperCase() !== 'A') throw "$.fn.pjax or $.pjax.click requires an anchor element" // 2. 使用鼠标滚轮点击(新标签页打开) // 点击超连接的同时按下Shift、Ctrl、Alt和Meta(在Windows键盘中是Windows键,在苹果机中是Cmd键) // 做用分别表明新窗口打开、新标签打开(不切换标签)、下载、新标签打开(切换标签) if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return // 3. 跨域(网络通信协议,域名不一致) if (location.protocol !== link.protocol || location.hostname !== link.hostname) return // 4. 当前页面的锚点定位 if (link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location)) return // 5. 已经阻止元素发生默认的行为(url跳转) if (event.isDefaultPrevented()) return ... var clickEvent = $.Event('pjax:click') $(link).trigger(clickEvent, [opts]) // 6. pjax:click事件回调中已经阻止元素发生默认的行为(url跳转) if (!clickEvent.isDefaultPrevented()) { pjax(opts) event.preventDefault()// 阻止url跳转 $(link).trigger('pjax:clicked', [opts]) } }
除了上述状况以外,还有下列几种状况:jquery
实际操做中出现问题:
pajx在浏览器回退和前进是无任何问题的。但若是你进行刷新或F5操做。那么加载出来的页面仅仅为地址栏后台请求出来的页面:好比,若是你的菜单栏项是经过pjax(这里请求的页面dom为 a/list.html)加载对应的内容到指定div(这里假设为div1)。那么若是进行了刷新或F5操做后页面出现的仅仅为 a/list.html页面的布局和信息。如何解决?
pajx在提交的头信息中包括了 x-pjax: true
git
1.服务器端判断是否为x-pjax请求github
服务器后台可经过该字段来判断是否为x-pjax请求。或者本身定义好参数传到后台来区分是不是x-pjax的请求。ajax
2.若是不为x-pjax请求则转发到首页地址跨域
若是你菜单项的首页为index.html 则转发到该页面。那么在刷新后就可以跳转到首页。包含了菜单项等。浏览器
@Controller public class TestController { @RequestMapping("/") public String index(){ return "index"; } @RequestMapping("/data") public String test(HttpServletRequest request){ boolean b = Boolean.valueOf(request.getHeader("x-pjax")); if(b){ }else{ return "redirect:/"; } return "test"; } }