yiisoft / jquery-pjax
pushState + ajax = pjax,由 Yii 框架核心开发者维护的分支
Requires
- yiisoft/jquery: >=1.8
README
pjax 是一个 jQuery 插件,使用 ajax 和 pushState 提供带有真实永久链接、页面标题和可用的后退按钮的快速浏览体验。
pjax 通过从您的服务器通过 ajax 获取 HTML 并将页面中容器元素的现有内容替换为加载的 HTML 来工作。然后它使用 pushState 更新浏览器中的当前 URL。这导致页面导航速度更快,原因有两个
- 不重新执行或重新应用页面资源(JS、CSS);
- 如果服务器配置为 pjax,则它可以只渲染部分页面内容,从而避免潜在的完整布局渲染。
此项目状态
当前,jquery-pjax 的维护工作大量停止。它可能还会收到重要的错误修复,但 其功能集已冻结,它不太可能获得新功能或改进。
安装
pjax 依赖于 jQuery 1.8 或更高版本。
Yii 2.0
由于它已经随 Yii 2.0 预装,因此无需手动安装库。
bower
$ bower install yii2-pjax
独立脚本
或者,将 yii2-pjax
添加到您应用的 bower.json
文件中。
"dependencies": { "yii2-pjax": "latest" }
独立
pjax 可以直接下载到您的应用公共目录中 - 确保您首先已加载 jQuery。下载并包含 jquery.pjax.js
到您的网页中
curl -LO https://raw.github.com/yiisoft/jquery-pjax/master/jquery.pjax.js
用法
$.fn.pjax
最简单和最常用的 pjax 用法如下
$(document).pjax('a', '#pjax-container')
这将启用页面上的所有链接的 pjax 功能,并将容器指定为 #pjax-container
。
如果您正在迁移现有站点,您可能不想立即在所有地方启用 pjax。而不是使用全局选择器 a
,请尝试使用 data-pjax
注释可 pjax 的链接,然后使用 'a[data-pjax]'
作为选择器。或者,尝试此选择器,它匹配 <div data-pjax>
容器内的任何 <a data-pjax href=>
链接
$(document).pjax('[data-pjax] a, a[data-pjax]', '#pjax-container')
服务器端配置
理想情况下,您的服务器应通过查看特殊的 X-PJAX
HTTP 标头来检测 pjax 请求,并仅渲染旨在替换容器元素内容的 HTML(在我们的示例中为 #pjax-container
),而不包含其余的页面布局。以下是在 Ruby on Rails 中可能实现此方法的示例
def index if request.headers['X-PJAX'] render :layout => false end end
如果您希望比 pjax 更自动化的 Rails 解决方案,请查看 Turbolinks。
还可以查看RailsCasts #294: 玩转PJAX。
参数
$.fn.pjax
函数的概述如下:
$(document).pjax(selector, [container], options)
selector
是一个字符串,用于点击事件委托。container
是一个字符串选择器,用于唯一标识pjax容器。options
是一个对象,其键如下所述。
pjax选项
键 | 默认值 | 描述 |
---|---|---|
timeout |
650 | 在强制刷新之前,在毫秒数内ajax超时 |
push |
true | 在导航时使用pushState添加浏览器历史记录条目 |
replace |
false | 替换URL而不添加浏览器历史记录条目 |
maxCacheLength |
20 | 之前容器内容的最大缓存大小 |
version |
返回当前pjax版本的字符串或函数 | |
scrollTo |
0 | 导航后滚动到的垂直位置。要避免更改滚动位置,请传递false 。如果设置为true ,页面将滚动到pjax容器。也可以是一个带有上下文和当前哈希作为参数的回调函数。例如:function (context, hash) { if (!hash) return $(context).offset().top; } |
scrollOffset |
0 | 添加到scrollTo 的垂直偏移。可以是一个带有当前scrollTo 值的回调函数。 |
type |
"GET" |
参见$.ajax |
dataType |
"html" |
参见$.ajax |
container |
替换内容的元素的CSS选择器 | |
url |
link.href | 用于ajax请求的URL的字符串或函数 |
target |
link | 最终是pjax事件的relatedTarget 值 |
fragment |
从ajax响应中提取的片段的CSS选择器 | |
pushRedirect |
false | 在重定向时是否添加浏览器历史记录条目 |
replaceRedirect |
true | 在重定向时是否替换URL而不添加浏览器历史记录条目 |
skipOuterContainers |
false | 当pjax容器嵌套且此选项为true时,最近的pjax块将处理事件。否则,将处理顶部的容器。 |
ieRedirectCompatibility |
true | 是否为IE请求添加X-Ie-Redirect-Compatibility 头部。修复了IE在302重定向时没有Location 头部的错误 |
您可以通过写入$.pjax.defaults
对象来全局更改默认值。
$.pjax.defaults.timeout = 1200
$.pjax.click
这是一个由$.fn.pjax
本身使用的较低级别的函数。它允许您对pjax事件处理获得更多的控制。
此示例使用当前点击上下文将祖先元素设置为容器
if ($.support.pjax) { $(document).on('click', 'a[data-pjax]', function(event) { var container = $(this).closest('[data-pjax-container]') var containerSelector = '#' + container.id $.pjax.click(event, {container: containerSelector}) }) }
注意使用显式的$.support.pjax
保护。我们没有使用$.fn.pjax
,因此除非浏览器实际上将使用pjax,否则应避免绑定此事件处理器。
$.pjax.submit
通过pjax提交表单。
$(document).on('submit', 'form[data-pjax]', function(event) { $.pjax.submit(event, '#pjax-container') })
$.pjax.reload
使用 pjax 机制向服务器发起对当前 URL 的请求,并用响应替换容器。不会添加浏览器历史条目。
$.pjax.reload('#pjax-container', options)
$.pjax
手动 pjax 调用。主要在您想要在一个未由点击事件发起的处理程序中启动 pjax 请求时使用。如果您可以访问到 event
,请考虑使用 $.pjax.click(event)
。
function applyFilters() { var url = urlForFilters() $.pjax({url: url, container: '#pjax-container'}) }
事件
除了 pjax:click
和 pjax:clicked
之外的所有 pjax 事件都由 pjax 容器元素触发。
event | cancel | arguments | notes |
---|---|---|---|
跟随 pjax 链接后的事件生命周期 | |||
pjax:click |
✔︎ | options |
从被激活的链接中触发;取消以阻止 pjax |
pjax:beforeSend |
✔︎ | xhr, options |
可以设置 XHR 头部 |
pjax:start |
xhr, options |
||
pjax:send |
xhr, options |
||
pjax:clicked |
options |
从被点击的链接开始后触发 | |
pjax:beforeReplace |
contents, options |
在用从服务器加载的内容替换 HTML 之前 | |
pjax:success |
data, status, xhr, options |
替换从服务器加载的 HTML 内容之后 | |
pjax:timeout |
✔︎ | xhr, options |
在 options.timeout 之后触发;除非取消,否则将进行硬刷新 |
pjax:error |
✔︎ | xhr, textStatus, error, options |
在 AJAX 错误时触发;除非取消,否则将进行硬刷新 |
pjax:complete |
xhr, textStatus, options |
总是触发 AJAX 之后,无论结果如何 | |
pjax:end |
xhr, options |
||
浏览器后退/前进导航的事件生命周期 | |||
pjax:popstate |
事件 direction 属性:"back"/"forward" |
||
pjax:start |
null, options |
在替换内容之前 | |
pjax:beforeReplace |
contents, options |
在用缓存内容替换 HTML 之前 | |
pjax:end |
null, options |
在替换内容之后 |
pjax:send
和 pjax:complete
是实现加载指示器的好搭档。只有当实际发出 XHR 请求时,它们才会被触发,而不是从缓存加载内容时。
$(document).on('pjax:send', function() { $('#loading').show() }) $(document).on('pjax:complete', function() { $('#loading').hide() })
取消 pjax:timeout
事件的示例可能是禁用如果显示旋转器时的回退超时行为。
$(document).on('pjax:timeout', function(event) { // Prevent default timeout redirection behavior event.preventDefault() })
高级配置
在新页面内容中重新初始化插件/小部件
pjax 的全部意义在于它在不刷新页面的情况下获取和插入新内容。然而,其他设置为对页面加载事件做出反应的 jQuery 插件或库(例如 DOMContentLoaded
)将不会检测到这些更改。因此,通常一个好的做法是将这些插件配置为在更新页面内容的范围内重新初始化。这可以通过以下方式完成
$(document).on('ready pjax:end', function(event) { $(event.target).initializeMyPlugin() })
这将使 $.fn.initializeMyPlugin()
在正常页面加载时在文档级别调用,并在任何 pjax 导航(无论是通过点击链接还是通过浏览器后退)后,在容器级别调用。
强制重新加载的响应类型
默认情况下,如果 pjax 从服务器接收到以下响应之一,它将强制页面完全重新加载
-
当没有明确配置
fragment
选择器时,包含<html>
的页面内容。Pjax 假设服务器的响应尚未正确配置用于 pjax。如果提供了fragment
pjax 选项,pjax 将根据该选择器提取内容。 -
空白页面内容。Pjax 假设服务器无法提供合适的 pjax 内容。
-
HTTP 响应代码为 4xx 或 5xx,表示某些服务器错误。
影响浏览器URL
如果服务器需要影响在Pjax导航后出现在浏览器URL中的URL(例如,HTTP重定向对正常请求的工作方式),它可以设置X-PJAX-URL
头信息
def index request.headers['X-PJAX-URL'] = "http://example.com/hello" end
布局重载
当资源或HTML发生变化时,可以强制布局执行硬重载。
首先,使用自定义元标签在您的页眉中设置初始布局版本。
<meta http-equiv="x-pjax-version" content="v123">
然后,从服务器端设置X-PJAX-Version
头信息为相同值。
if request.headers['X-PJAX'] response.headers['X-PJAX-Version'] = "v123" end
部署部署,将版本常量提升以强制客户端在下一个请求中进行完整重载,获取新布局和资源。