Reveal.js内嵌iframe页面跳转链接如何支持hash路径直接访问
Reveal.js iframe内嵌页路由同步实现方案
核心思路是做外层Reveal幻灯片hash路由和内嵌iframe页面内部路径的双向绑定,就能实现https://www.xx/#/xx/xa格式的URL直接访问对应内嵌内容,具体实现分三步:
1. 调整外层幻灯片配置
原有iframe嵌入的section标签不需要改结构,保留原有属性即可:
<section id="xx" data-background-iframe="xx.html" data-background-interactive></section>
初始化Reveal时必须开启hash路由支持,同时添加基础路由监听逻辑:
Reveal.initialize({ hash: true, // 保留你原有其他配置项 }) // 页面首次加载时解析初始hash,直接定位目标内容 window.addEventListener('load', () => { const hashConfig = window.location.hash.replace(/^#\//, '').split('/') // 匹配#/幻灯片id/内嵌路径的格式 if (hashConfig.length >= 2 && hashConfig[0] === 'xx') { // 先切换到对应id的幻灯片页 const targetSlide = document.querySelector('#xx') Reveal.slide(Reveal.getIndices(targetSlide).h) // 等iframe加载完成后同步内部路径 const syncIframePath = () => { const innerPath = '/' + hashConfig.slice(1).join('/') targetSlide.backgroundiframe.contentWindow.postMessage({ type: 'sync-route', path: innerPath }, window.location.origin) } if (targetSlide.backgroundiframe) { targetSlide.backgroundiframe.addEventListener('load', syncIframePath, { once: true }) } } }) // 监听内嵌页发来的跳转请求,更新外层hash window.addEventListener('message', (e) => { if (e.origin !== window.location.origin) return if (e.data?.type !== 'inner-nav') return const { slideId, path } = e.data const newHash = `#/${slideId}${path}` if (window.location.hash !== newHash) { window.history.pushState({}, '', newHash) } })
2. 修改内嵌页(xx.html)的跳转逻辑
原生a标签默认跳转会触发整页刷新,直接跳出Reveal容器,所以要拦截跳转行为,和父页面做状态同步。
首先给需要触发内部跳转的a标签加标识,原有链接地址不用修改:
<a href="/xa" class="reveal-inner-link">jump link</a>
在xx.html里加入以下脚本:
// 拦截内部链接点击,同步状态给父页面 document.querySelectorAll('.reveal-inner-link').forEach(link => { link.addEventListener('click', (e) => { e.preventDefault() const targetPath = link.getAttribute('href') // 通知父页面更新hash window.parent.postMessage({ type: 'inner-nav', slideId: 'xx', path: targetPath }, window.location.origin) // 更新当前iframe的路径 window.history.pushState({}, '', targetPath) // 这里替换成你自己页面的内容渲染逻辑:如果是SPA就触发路由匹配渲染,静态页就做对应内容显隐 }) }) // 接收父页面的路由同步指令,处理直接访问带hash URL的场景 window.addEventListener('message', (e) => { if (e.origin !== window.location.origin) return if (e.data?.type !== 'sync-route') return const targetPath = e.data.path window.history.pushState({}, '', targetPath) // 同样在这里触发对应路径的内容渲染逻辑 })
3. 特殊场景适配
- 如果内嵌页是服务端渲染的多页应用,没有前端路由,可以把
pushState逻辑替换为iframe.contentWindow.location.replace(targetPath),注意加路径判断避免重复刷新触发循环 - 跨域部署场景下,把
postMessage的origin参数改成你实际的业务域名,不要用*避免安全风险 - 如果需要支持浏览器前进后退,可以给内外层都加
popstate事件监听,逻辑和上面的路由同步逻辑一致即可
内容的提问来源于stack exchange,提问作者ideewirwa
相关产品推荐
相关产品推荐

