注册
web

【日常总结】iframe内嵌网站初始路由404解决

背景


Vue 项目被嵌入到 <iframe> 中,通过src加载页面,结果打开后直接访问404,但是如果不是通过iframe打开的话是不会出现这个问题的。

<iframe src="/dist/index.html"></iframe>



问题现象


在首次进入时,Vue Router 没有正确地导航到首页路由,而是到了404页面。


349400e6e0d31a5b2d63596e7a0d93ad.png


原因


vuerouter内部match当前路径的逻辑在这种情况下有问题,所以取到的是错误的信息,找不到这个path,就跳转到了404。前端路由是要依赖当前路径来做处理的,而路径是依赖location字段,但这个时候location跟我们预期的不一样,就跳转错误。


885de24d06f9119ce468db4936b042bf.png


为什么会这样?


是因为iframe 的加载是异步的,router路径跳转之前iframe还没初始化好,导致router内部获取的当前路径不对。


f6147aa890634152a95cf1b5798782ca.png


所以思路有2个:



  1. 路径redirect有问题,那就不依赖它,在url中增加参数设置正确的首次跳转路径
  2. 在 iframe 加载完成时,设置正确的路由信息从而导航过去。所以就从iframe加载完后重新设置导航这个关键点下手。

梳理到这里,我意识到上面两种方案是iframe的通信方式:



  • url传递信息
  • postMessage传递消息

解决方案


方案一:iframe的src的URL 参数中增加初始路由信息



  1. 在 iframe 的 src 属性中通过url参数添加首页的路由信息,
<iframe src="/dist/index.html?route=/dashboard"></iframe>


  1. 再在 Vue 应用程序初始化时,如果读取到了router则跳转过去。
import Vue from 'vue'
import App from './App.vue'
import router from './router'

// 方案1:根据添加的url参数判断
const routeParam = new URLSearchParams(window.location.search).get('route');
if (routeParam) {
router.push(routeParam);
}

new Vue({
router,
render: h => h(App),
}).$mount('#app')

我使用的这种方案。


方案二:使用 postMessage 实现父页面和iframe的通信



  1. 父页面监听iframe加载完后通过postMessage发送消息:
const iframe = document.getElementById('myIframe');
if (iframe) {
iframe.onload = function() {
iframe.contentWindow.postMessage({ route: '/dashboard' }, '*');
};
}


  1. iframe内页面main.ts中监听消息,设置路由
// 方案2:postMessage来实现iframe的通信
window.addEventListener('message', handleMessage, false);

function handleMessage(event: any) {
const { data } = event;
if (data.route) {
console.log('message', event, data.route);
router.push(data.route); // 导航到接收到的路由
}
}

这个方案,也可以fix这个bug,但是会先闪到404,再到首页,原因应该是iframe通信是要放到onmounted钩子里的,因为依赖dom加载完,所以会有个时间差。等到iframe onload时候之前已经redirect到404了,然后又重新route了下,效果不是很好。


方案三:利用路由钩子


利用 Vue Router 的导航守卫,在路由导航前检查 URL 参数中是否存在初始路由信息,如果存在则进行相应的导航处

// 方案3: 路由拦截
router.beforeEach((to, from, next) => {
if (to.matched.length === 0) {
// 如果未匹配到任何路由,说明当前页面可能是初始加载
next('/dashboard/base'); // 或者重定向到默认页面
} else {
next(); // 继续正常导航
}
});

结果


先把今天遇到的问题简单总结下:




  • 最后采用了方案1。




  • 方案2 调试出来了,但是效果会有先闪过404页面,后续又到首页的情况,效果不是很好。




  • 3没调出来,暂时不调了。

































标题优点缺点问题
url加参数简单,直接,只需要在内嵌的项目写代码url结构不好看最终使用
postmenssage不需要修改url需要内嵌iframe的页面和iframe的项目中添加额外代码会有一闪而过的效果,体验不好
beforeEach不需要修改url路由钩子每个都处理了逻辑有问题,没调试出来

作者:searchop
链接:https://juejin.cn/post/7338053219994796082
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册