nkovacs/jquery-pjax

pushState + ajax = pjax,由 Yii 框架核心开发者维护的分支

安装量: 12,526

依赖者: 0

建议者: 0

安全: 0

星标: 2

关注者: 4

分支: 1,970

开放问题: 0

语言:JavaScript

v3.0.0 2019-09-24 14:00 UTC

This package is auto-updated.

Last update: 2024-08-25 03:42:11 UTC


README

        .--.
       /    \
      ## a  a
      (   '._)
       |'-- |
     _.\___/_   ___pjax___
   ."\> \Y/|<'.  '._.-'
  /  \ \_\/ /  '-' /
  | --'\_/|/ |   _/
  |___.-' |  |`'`
    |     |  |
    |    / './
   /__./` | |
      \   | |
       \  | |
       ;  | |
       /  | |
 jgs  |___\_.\_
      `-"--'---'

简介

pjax 是一个 jQuery 插件,使用 ajax 和 pushState 提供具有真实永久链接、页面标题和可工作的后退按钮的快速浏览体验。

pjax 通过从您的服务器通过 ajax 获取 HTML 并用ajax获取的 HTML 替换页面容器的内容来工作。然后使用 pushState 更新浏览器当前 URL,而不会重新加载页面布局或任何资源(JS、CSS),给人一种快速、完整页面加载的错觉。但实际上只是 ajax 和 pushState。

对于不支持 pushState 的浏览器,pjax 会完全降级。

概述

pjax 不是完全自动的。您需要在您的页面上设置并指定一个包含元素,该元素在您导航网站时将被替换。

考虑以下页面。

<!DOCTYPE html>
<html>
<head>
  <!-- styles, scripts, etc -->
</head>
<body>
  <h1>My Site</h1>
  <div class="container" id="pjax-container">
    Go to <a href="/page/2">next page</a>.
  </div>
</body>
</html>

我们希望 pjax 捕获 URL /page/2 然后用返回的内容替换 #pjax-container。不会重新加载任何样式或脚本,甚至 <h1> 也可以保持不变 - 我们只是想改变 #pjax-container 元素。

我们通过告诉 pjax 监听 a 标签并使用 #pjax-container 作为目标容器来实现这一点

$(document).pjax('a', '#pjax-container')

现在当有人在兼容 pjax 的浏览器上点击“下一页”时,#pjax-container 的内容将被替换为 /page/2 的主体。

魔法!几乎。您仍然需要配置您的服务器以查找 pjax 请求并返回 pjax 特定的内容。

pjax ajax 请求发送一个 X-PJAX 标头,因此在这个例子(以及在大多数情况下)我们只想返回页面的内容,而不包括任何布局。

以下是在 Rails 中的可能样子

def index
  if request.headers['X-PJAX']
    render :layout => false
  end
end

如果您需要一个比 pjax 更自动化的解决方案,请查看 Turbolinks

还可以查看 RailsCasts #294: Playing with PJAX

安装

Yii 2.0

由于它预装在 Yii 2.0 中,因此无需手动安装库。

bower

通过 Bower

$ bower install yii2-pjax

或者,将 yii2-pjax 添加到您的应用的 bower.json 文件中。

  "dependencies": {
    "yii2-pjax": "latest"
  }

独立

pjax 可以直接下载到您的应用的公共目录中 - 只需确保您首先加载了 jQuery。

curl -LO https://raw.github.com/yiisoft/jquery-pjax/master/jquery.pjax.js

警告 不要直接链接原始脚本 URL。GitHub 不是一个 CDN。

依赖关系

需要 jQuery 1.8.x 或更高版本。

兼容性

pjax 只与支持 history.pushState API 的浏览器一起工作。当该 API 不受支持时,pjax 会进入降级模式:`$.fn.pjax` 调用将不会执行任何操作,`$.pjax` 将强制加载给定的 URL。

出于调试目的,即使浏览器支持 `pushState`,您也可以故意禁用 pjax。只需调用 `$.pjax.disable()`。要查看 pjax 是否实际支持 `pushState`,请检查 `$.support.pjax`。

用法

$.fn.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')

参数

$.fn.pjax函数的概述是

$(document).pjax(selector, [container], options)
  1. selector是一个用于点击事件代理的字符串。
  2. container是一个唯一标识pjax容器的字符串选择器。
  3. options是一个具有以下键的对象。
pjax选项

您可以通过写入$.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]')
    $.pjax.click(event, {container: container})
  })
}

注意 使用显式的$.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:clickpjax:clicked之外的所有pjax事件都从pjax容器而不是被点击的链接中触发。

pjax:sendpjax: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()
})

服务器端

服务器配置将在不同的语言和框架之间有所不同。以下示例显示了如何配置Rails。

def index
  if request.headers['X-PJAX']
    render :layout => false
  end
end

设置一个X-PJAX请求头,以区分pjax请求和常规XHR请求。在这种情况下,如果请求是pjax,我们跳过布局html,只渲染容器的内部内容。

检查您最喜欢的服务器框架是否有pjax插件

强制重新加载的响应类型

默认情况下,如果pjax从服务器收到以下响应之一,它将强制整个页面重新加载

  • 当没有明确配置fragment选择器时,页面内容包含<html>。Pjax假设服务器的响应还没有为pjax正确配置。如果提供了fragment pjax选项,pjax将简单地提取内容,根据该选择器将其插入DOM中。

  • 空白页面内容。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标签在您的标题中设置初始布局版本。

<meta http-equiv="x-pjax-version" content="v123">

然后,从服务器端设置X-PJAX-Version头为相同的值。

if request.headers['X-PJAX']
  response.headers['X-PJAX-Version'] = "v123"
end

部署一个部署,将版本常量提升以强制客户端在下次请求时进行完全重新加载,获取新的布局和资源。