原文來自個人小站:Pjax加持APlayer,音樂無間斷,轉(zhuǎn)載請備注
起因
下午在 @櫻花莊的白貓 博客中看到左下角有個小小的音樂播放器,新奇的東西 F12 上,瞅一下名字:aplayer,啥?!谷哥度娘走起
首條記錄上就出現(xiàn)了 APlayer 的官方網(wǎng)站,這么簡單嘛?!只要有文檔,一切都好說嘛。跟著導(dǎo)航找找找,是你了!吸附底邊的播放樣式:

APlayer 可以通過吸底模式固定在頁面底部。
APlayer播放器
官方對它的介紹:
?? Wow, such a beautiful HTML5 music player
確實(shí)挺好看的,支持各種樣式,本破小站只要有個簡單的左下角 “吸底模式” 就好,代碼引用也簡單,保姆式文檔上就貼了:
首先,div容器,樣式和核心jio本(文檔有給出 jsdelivr 的 CDN 鏈接)
<link rel="stylesheet" >
<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10.0/dist/APlayer.min.js"></script>
<div id="aplayer"></div>
然后進(jìn)行初始化
const ap = new APlayer({
container: document.getElementById('player'),
fixed: true,
audio: [{
name: 'name',
artist: 'artist',
url: 'url.mp3',
cover: 'cover.jpg',
}]
});
好了,加上MP3的外鏈,愉快的聽歌吧~~????(別說你獲取不到MP3外鏈,那就趕緊去拜托谷哥度娘吧)

你以為文章就到此結(jié)束了嗎?額...在下也希望是這樣,碼字可是很痛苦的
??
??
??
神器 Pjax
Pjax 又是啥?別急,聽在下說說新的麻煩:
沉浸中歡樂的歌聲中,隨便點(diǎn)了一個頁內(nèi)跳轉(zhuǎn),網(wǎng)頁開始刷新,但是!但是!但是!音樂播放器也跟著刷新了,從頭開始播放?!Excuse Me?這也太傻了吧...
轉(zhuǎn)念細(xì)想,其實(shí)按上面的教程,是在每個 html 頁面上都加上了 APlayer 的加載代碼,頁面刷新的時候,上個頁面自然的就被替換成了新的頁面,APlayer 就相當(dāng)于重新加載了一次。所以,講道理,這段代碼應(yīng)該只用加載一次,并且不能隨著網(wǎng)頁跳轉(zhuǎn)而改變,就像被我埋沒多年的 QQ 空間那樣(每次翻看太多黑歷史了,但音樂播放器是優(yōu)秀的)。
網(wǎng)上有人說可以用框架做,就是一個框架中嵌入 APlayer,另一個用于頁面跳轉(zhuǎn);也有人說用 Pjax,它可以做到無刷新 ajax 加載??紤]再三(也就幾秒鐘),肯定拋棄前者這種過時的方法,積極擁抱 jQuery-Pjax 。
pjax = pushState + ajax 的縮寫,它通過 ajax 和 pushState 技術(shù)提供了極速的(無刷新 ajax 加載)瀏覽體驗(yàn),并且保持了真實(shí)的地址、網(wǎng)頁標(biāo)題,瀏覽器的后退(前進(jìn))按鈕也可以正常使用。pjax 的工作原理是通過 ajax 從服務(wù)器端獲取 HTML,在頁面中用獲取到的 HTML 替換指定容器元素中的內(nèi)容。然后使用 pushState 技術(shù)更新瀏覽器地址欄中的當(dāng)前地址。
以下兩點(diǎn)原因決定了 pjax 會有更快的瀏覽體驗(yàn):
- 不存在頁面資源(js/css)的重復(fù)加載和應(yīng)用;
- 如果服務(wù)器端配置了 pjax,它可以只渲染頁面局部內(nèi)容,從而避免服務(wù)器渲染完整布局的額外開銷。
下面介紹下常用操作:
-
引入 jQuery-Pjax 腳本
<script src="https://cdn.bootcss.com/jquery.pjax/2.0.1/jquery.pjax.min.js"></script> -
在 HTML 中準(zhǔn)備替換的內(nèi)容用 div 包裹起來,id自定義,類似如下
<body> ... <div id="pageContent"> <!--include content.html--> </div> <div id="aplayerContent"> <!--include aplayer.html--> </div> ... </body>#pageContent里面是本破小站的主要容器,而#aplayerContent里面就是 Aplayer 的核心內(nèi)容了 -
接管網(wǎng)站所有 a 標(biāo)簽跳轉(zhuǎn),注意我們這里不需要后臺的話,記得一定要添加 fragment 指定為 pjax 容器。
$(document).pjax('a[target!=_blank]', '#pageContent', {fragment: '#pageContent'});
通過這種方式可以讓頁面中所有的鏈接都實(shí)現(xiàn)了 Pjax 加載,并指定 #pageContent 作為容器元素。如此,頁內(nèi)不管怎么跳轉(zhuǎn)都只是刷新了 #pageContent 容器,而不會影響到 Aplayer 的音樂播放啦。
好了,再次愉快的聽歌和盡情的刷網(wǎng)頁瀏覽吧~~~????
然而......還沒完
??
??
??
深思
其實(shí)這種改變整個網(wǎng)站跳轉(zhuǎn)模式的做法,站在程序的角度上,無疑是底層的大改,會觸動很多東西,牽一發(fā)而動全身,是很抵觸的。
但若非如此,Aplayer 的播放問題得不到解決,不管用哪種方式去實(shí)現(xiàn),都動到了底層的邏輯。無耐,本著折騰的心一路走到黑吧。
Valine路徑問題
首先發(fā)現(xiàn)最大的問題:前幾天剛接入的 Valine 用 Pjax 跳轉(zhuǎn)后,評論得不到加載,甚至評論框都時好時壞????。
經(jīng)過幾天的查閱各種官方文檔和看他們底下的評論(Valine,jQuery, Pjax都快被在下翻爛了),各種冥想,總結(jié),一個個方法嘗試,總算是比較好的解決了。問題主要以下:
-
Valine的window.location.pathname必須顯式的指定let valine = new Valine({ el: '#vcomments', appId: 'your appId', appKey: 'your appKey', path: window.location.pathname, // 這里!!!必要顯式的指定為window.location.pathname });按官方文檔的說法,path 的默認(rèn)值就是
window.location.pathname,可以不指定,但若用 Pjax 跳轉(zhuǎn)不指定就是不行,你說氣不氣。 -
跳轉(zhuǎn)頁面的url問題(自己的原因)
原本的代碼:
<li> <a href="/docs/Awesome">Awesome</a> </li> <li> <a href="/docs/Reading">Reading</a> </li>若不用 Pjax 原本的瀏覽器刷新會在路徑最后自動會補(bǔ)上一個
"/",所以 Valine 按window.location.pathname去加載評論時都會帶上"/"作為 URL 的,而 Pjax 使用時雖然你的路徑也能正確解析出 HTML 內(nèi)容,但去做評論查找時,這 URL 就對不上了,就會得到空白的結(jié)果。修正:
<li> <a href="/docs/Awesome/">Awesome</a> </li> <li> <a href="/docs/Reading/">Reading</a> </li> -
對 1 的增強(qiáng),有時候顯式指定了
path: window.location.pathname還是不行因此,對 Pjax 做了一個事件監(jiān)聽
pjax:beforeReplace(從服務(wù)器端加載的 HTML 內(nèi)容完成之后,替換當(dāng)前內(nèi)容之前),在這個生命周期中,再次指定 path:$(document).on('ready pjax:beforeReplace', function (event) { valine.setPath(pathname); });
經(jīng)過上面的幾點(diǎn)修復(fù),到現(xiàn)在為止,Valine 總算又可以正常的使用了,暫時沒發(fā)現(xiàn)新的問題。
除 Valine 外,其他方面上的坑:
-
文章側(cè)欄導(dǎo)航因 Pjax 的前進(jìn)后退導(dǎo)致重復(fù)添加
fix:每次預(yù)清理就好
-
404/offline 頁面回退后,樣式殘留
fix:監(jiān)聽
pjax:clicked事件,然后做樣式清除
暫時就沒發(fā)現(xiàn)還有其他的大問題,有就來一個修一個吧????
最后總結(jié)
一開始 我真的只是 單純的 想加個 音樂播放器 而已......