张登友,张登友的博客,张登友的网站——
使用pjax无刷新加载网页,实现切换页面音乐不间断播放
Pjax 原理
首先要知道 Pjax = Ajax + pushState
。当用户进行超链请求时,Pjax 会拦截请求,然后触发 Ajax 请求和 pushState。其中,Ajax 使你的页面局部刷新,pushState 用于修改 URL 而不跳转页面,从而实现不跳转页面局部刷新的功能。
官方文档解释
- 它监听您想要的每个链接点击(默认情况下都是)。
- 单击内部链接时,Pjax通过AJAX获取页面的HTML。
- Pjax渲染页面的DOM树(不加载任何资源-图像、CSS、JS等)。
- 它检查是否可以更换所有定义的部件:
- 如果页面不符合要求,则使用标准导航。
- 如果页面满足要求,Pjax将进行所有定义的DOM替换。
pushState
用于修改 URL 而不跳转页面
安装pjax
Pjax 有依赖和不依赖 jQuery 的两种版本:
- defunkt/jquery-pjax【依赖于 jQuery】
- MoOx/pjax【推荐】
引用文件
我这里使用npm安装(二选一安装即可)
npm install pjax # 原生命令安装
cnpm install pjax # 淘宝加速镜像安装
然后在页面引入
<script src="./node_modules/pjax/pjax.js"></script>
或者直接使用 JSDelivr 公共的 CDN 地址(推荐)
<script src="https://cdn.jsdelivr.net/npm/pjax/pjax.js"></script>
创建实例化对象
实例化Pjax并将选项作为对象传递给构造函数:
let pjax = new Pjax({
selectors: ["head title", ".aa", ".pp"],//填写要改变的部分,标签直接写标签名,id选择器需要加#,类名需要加.
history: true, //是否添加近浏览器历史记录
pushState: true,//是否启用 pushState。禁用后 Pjax 就变成了 Ajax。
scrollRestoration: true,//切换页面后,Pjax 将尝试恢复滚动位置。
cacheBust: false //是否在 URL 上添加时间戳,防止浏览器缓存。
});
重载pjax
因为pjax本身也会被自己拦截而不进行刷新,这会导致在第二个页面无法执行,并且使网页全部刷新,这时候我们需要在pajx执行完成之后重新再创建一次pjax构造对象(其他需要重新加载的函数同理,比如valine和waline评论模块)
function pjax_reload() {
//其他需要重新加载的函数也可以添加在这里
let pjax = new Pjax({
selectors: ["head title", ".aa", ".pp"],
history: true,
pushState: true,
scrollRestoration: true,
cacheBust: false
});
}
// Pjax 完成后,重新加载上面的函数
document.addEventListener("pjax:complete", function () {
pjax_reload();
});
加载音乐播放器
<div id="player"></div> <!-- 音乐播放器的容器 -->
<script src="js/APlayer.min.js"></script> <!-- 引入aplayer播放器的js文件 -->
<!-- 实例化音乐播放器 -->
<script>
function music(data) {
let ap = new APlayer({
container: document.getElementById('player'),
fixed: true,
autoplay: false,
theme: '#FADFA3',
loop: 'all',
order: 'random',
preload: 'auto',
volume: 0.7,
listFolded: false,
listMaxHeight: 90,
lrcType: 3,
audio: [{
"name": "侧脸",
"artist": "于果",
"url": "./music/侧脸-于果.flac",
"cover": "./cover/1.png",
"lrc": "./music/aa.lrc"
}, {
"name": "哈哈哈",
"artist": "测试",
"url": "./music/侧脸-于果.flac",
"cover": "./cover/1.png",
"lrc": "./music/aa.lrc"
}]
});
}
music();
</script>
完整代码
最后贴出代码,若想测试的话,可以复制两份出来,将超链接改一下即可
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>主页</title>
<link rel="stylesheet" href="node_modules/aplayer/dist/APlayer.min.css">
<script src="./node_modules/pjax/pjax.js"></script>
</head>
<body>
<a class="aa" href="index2.html">测试网页1</a>
<p class="pp">测试文本</p>
<div id="player"></div>
<p class="pp">哈哈哈哈哈</p>
<script>
let pjax = new Pjax({
selectors: ["head title", ".aa", ".pp"],
history: true,
pushState: true,
scrollRestoration: true,
cacheBust: false
});
function pjax_reload() {
let pjax = new Pjax({
// 这里由于加载pjax,函数本身也用了无刷新,再加载第二个网页时会报错,需要进行重载
selectors: ["head title", ".aa", ".pp"],
history: true,
pushState: true,
scrollRestoration: true,
cacheBust: false
});
}
// Pjax 完成后,重新加载上面的函数
document.addEventListener("pjax:complete", function () {
pjax_reload();
});
</script>
<script src="js/APlayer.min.js"></script>
<script>
//aplayer音乐播放器
function music() {
let ap = new APlayer({
container: document.getElementById('player'),
fixed: true,
autoplay: false,
theme: '#FADFA3',
loop: 'all',
order: 'random',
preload: 'auto',
volume: 0.7,
listFolded: false,
listMaxHeight: 90,
lrcType: 3,
audio:
// 模拟请求到的数据
[{
"name": "侧脸",
"artist": "于果",
"url": "./music/侧脸-于果.flac",
"cover": "./cover/1.png",
"lrc": "./music/aa.lrc"
}, {
"name": "哈哈哈",
"artist": "测试",
"url": "./music/侧脸-于果.flac",
"cover": "./cover/1.png",
"lrc": "./music/aa.lrc"
}]
});
}
music();
</script>
</body>
</html>
使用效果
在我们重新加载网页之后,音乐没有被打断并且继续播放,开发工具里也是显示只替换了我们的在选择器里选择的title,p,和a
我的博客过段时间也会将这个功能合并进入(主要调试太费时间了,会出现很多bug,暂时不上线)
参考文章:https://liuyib.github.io/2019/09/24/use-pjax-to-your-site/