前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >给网站添加PJAX无刷新

给网站添加PJAX无刷新

原创
作者头像
圆弧
发布2025-02-20 21:49:20
发布2025-02-20 21:49:20
690
举报

在深入讨论PJAX之前,有必要先了解什么是AJAX及其扩展技术PJAX。AJAX(Asynchronous JavaScript and XML)是一种异步技术,旨在实现跨页操作而不需页面刷新。它通过将JavaScript和XML用于响应式加载内容,显著提升了网页的用户体验和性能。AJAX的主要特点是:当用户请求更多内容时,浏览器会延迟加载而非刷新页面,从而降低了等待时间并减少了资源消耗。最常见的应用是“瀑布流”布局,即在拉到底部时系统会逐步加载后续内容。这种技术无疑为网页开发提供了更高效的方式,使网站表现更加流畅。

PJAX(PushState and AJAX)是AJAX的一种扩展,旨在进一步提升用户体验。它通过在页面刷新时添加历史记录功能(通常表现为左侧和右侧的 ← 和 → 按钮),允许用户通过按钮快速返回到之前的状态而不需重新加载页面。这种特性特别适合需要快速切换状态的应用场景,显著提升了交互体验。

那么如何在自己的网站上实现PJAX呢?开源社区提供了多种解决方案,其中JQuery版本的PJAX因其流行性和丰富性备受关注。然而,对于不习惯或不想依赖JQuery的开发者来说,使用无库版本的PJAX组件(如Kico Style)是一个更简洁、高效的替代方案。

开源项目地址

https://github.com/MoOx/pjax

引入文件

你可以下载该js在自己的服务器上托管代码。或者是直接使用 JSDelivr 公共 CDN 友情提供的地址:

代码语言:txt
复制
<script src="https://cdn.jsdelivr.net/npm/pjax/pjax.js"></script>

建议将 JS 文件放在网站的底部,防止因文件加载过慢而导致的页面阻塞打开缓慢的情况。

开始使用

每个网站在刷新的过程中,总有一部分是重复的。在开始定义 PJAX 组件之前,我们首先需要分析一下那个需要添加 PJAX 的网页 DOM 结构,看看哪些元素/容器是需要被替换的。通过 Chrome 浏览器的开发工具,就可以更直观的看到它。 我们手动判断 DOM 结构,合理的编写 PJAX 替换页面内容所需要的选择器,就可以把在网页刷新过程中发生变化的那一部分给 “刷新”。

只要是个网站,每次切换页面的时候,title 标签是必然得替换的。在我这个案例中,main 是每次切换页面之后会产生内容变化的容器。而另外两个容器 header 和 footer 都是毫无变化的,这就无需编写了。如果想额外刷新一下 meta 标签,满足强迫症的要求(例如我)可以再加上 meta 选择器。

代码语言:txt
复制
var pjax = new Pjax({
  // 在页面进行 PJAX 时需要被替换的元素或容器,一条一个 CSS 选择器,数组形式
  selectors: [
    "title",
    "meta[name=description]", // 如果是全部 meta 替换的话,只需要写 meta
    "main"
  ],
  cacheBust: false
})

这样,一个灰常简单的 PJAX 网站就做好了!是不是非常简单呢?

重载函数

如果你的页面内容需要配合 JS 实现一些特效(例:图片灯箱),你可能会发现刚打开页面时所执行的 JS 效果失效了。这是由于 PJAX 修改了文档 DOM 结构,当前网页的内容已经发生了变化,那些曾被函数安排过的元素已经消失。 PJAX 不像刷新页面一样,浏览器不会从头到尾分析网站,因此不会自动重新执行一次 JS。我们为了保证这些功能能正常发挥他们的作用,所以需要重新让它再运行一次,这种操作我们称之为 “重载”。像基于 Kico Style 编写的网站,图片灯箱组件就需要重新执行一次。

代码语言:txt
复制
// 添加重载,其实就是 PJAX 完成之后的操作
document.addEventListener('pjax:complete', function (){
    // 需要重载的 JS 函数
    ks.image(":not[no-image] img"); // 重载 Kico Style 的图片灯箱
});

如果你的代码在函数体外部声明获取了一次元素(只在某些特定页面中出现的),为了保证这些元素在 PJAX 完成之后能再次生效,你需要重新声明。最好事先封装好一个类或是函数,这样就保证了代码的复用性。在 pjax:complete 事件函数中就可以直接调取它,快速实现 JS 的重载。

代码语言:txt
复制
// 像评论这种只在某些特定页面中出现的功能,不应单独写在函数体外面声明,对 PJAX 尤其不利
var comment = document.getElementsByClassName("comment-body")[0];

使用函数封装,提升代码复用性和可读性。

代码语言:txt
复制
function pjax_reload(){
    var comment = document.getElementsByClassName("comment-body")[0];
    ...
}

document.addEventListener('pjax:complete', function (){
    pjax_reload();
});

改善体验

在进行 PJAX 的过程中,浏览器是不会有任何加载提示的,也就是那个转圈圈的动画没有了。如果你的服务器速度比较一般的话,用户可能无法察觉到链接点击之后发生的事情,可能会认为点击没有反应。 我们可以给网站添加一个加载动画,在 PJAX 开始的时候显示它,在完成的时候隐藏它。下面这个是我现在所使用的一个案例,你也可以自己设计一个加载动画,使用图片什么的都是一样的。

HTML:

代码语言:txt
复制
<!- 添加一个加载提示 ->
<loader>
    <div class="plane"></div>
</loader>

CSS:

代码语言:txt
复制
loader{
    top: 2em;
    right: 2em;
    z-index: 3;
    opacity: 0;
    position: fixed;
    pointer-events: none;
    transition: opacity .3s;
}
loader.active{ opacity: 1 }

loader .plane{
    width: 2em;
    height: 2em;
    background: #0b63ff;
    animation: loader 1.2s infinite ease-in-out
}

@keyframes loader {
    0% {
        transform: perspective(120px) rotateX(0deg) rotateY(0deg)
    }
    50% {
        transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
    }
    100% {
        transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg)
    }
}

实现动画的基本逻辑就是在加载中的时候使得 loader 的透明度为 1 即不透明,在加载完成的时候为 0。在这里我们配合了 Kico Style 的快速选择器进行使用。如不需要,请使用 document.querySelector() 方法进行替代。

JavaScript:

代码语言:txt
复制
// 开始 PJAX 执行的函数
document.addEventListener('pjax:send', function (){
    ks.select("loader").classList.add("active");
});

// PJAX 完成之后执行的函数,可以和上面的重载放在一起
document.addEventListener('pjax:complete', function (){
    ks.select("loader").classList.add("active");
});

这样一个改善体验的加载动画也完成了!

其他参数

history:默认值 true 是否修改历史记录,如果关闭就相当于只有 AJAX 了

timeout:默认值 0 加载超时时间

cacheBust:默认值 true 是否添加额外的时间戳,防止浏览器进行缓存,默认 true,你改成 false 的话地址栏会更加好看。

scrollRestoration:默认值 true 是否尝试设置滚动位置,将在向后或向前导航时尝试恢复滚动位置。

后端延伸

PJAX 在发送请求的时候会自带一个 X-PJAX 头,默认为 X-PJAX: "true"。你可以通过这个头在后端判断是否为 PJAX 请求从而跳过一部分内容的输出,减小服务器对部分资源的请求并实现更小的回复内容。 该组件还有一些高级的功能,例如加载时调用动画库等操作,都可以在该项目的 README 中寻找答案。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开源项目地址
  • 引入文件
  • 开始使用
  • 重载函数
  • 改善体验
  • 其他参数
  • 后端延伸
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档