让你的Hexo变成单页面应用

在开始之前,不妨先打开这个页面,播放一首音乐,再点击我的头像返回来。

你是不是会好奇,明明是由Hexo生成的静态页面,为什么没有触发浏览器刷新?

静态页面虽然对SEO友好,但是却让访客的浏览体验不佳——现如今几乎没有不需要进行交互的网页。而只需要使用Fetch API,将页面作为一种资源异步取得,再由Javascript进行解析和局部替换,就让整个网站看起来像是单页应用了

    <!-- html -->
    <a href="/audio/" onclick="onEvent(event);return false">声 音</a>
// typescript

async function _appendScript(element: HTMLScriptElement) {
    return new Promise((resolve) => {
        if (!element.src) {
            // e.innerText = element.innerText
            return
        }
        const e = document.createElement('script')
        document.body.appendChild(e)
        e.src = element.src
        e.onload = () => {
            resolve({})
        }
    })

}

/**
 * 模拟单页面应用
 * @param event
 */
async function onEvent(event: MouseEvent): Promise<void> {
    const el = event.target as HTMLLinkElement
    if (!el.href) {
        return onEvent({ target: el.parentElement } as any)
    }

    const res = await fetch(el.href)
    const data = await res.text()
    const domparser = new DOMParser()
    const doc = domparser.parseFromString(data, 'text/html')

    window.history.pushState(null, doc.title, el.href)

    document.title = doc.title
    document.body = doc.body
    let scripts: HTMLScriptElement[] = doc.body.querySelectorAll('script') as any
    if (!scripts) scripts = []
    else scripts = Array.from(scripts)

    for (let i = 0; ; i++) {
        if (i >= scripts.length) {
            break
        }
        const s = scripts[i]
        await _appendScript(s)
    }

}