在vue中使用iframe标签
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在vue中使用iframe标签相关的知识,希望对你有一定的参考价值。
参考技术A 在vue中使用iframe标签时,打包后的src文件无法查看会报路径不对404等可以把iframe中的src路径改成打包后的文件路径即可;
在 iframe / 对象标签内运行时更新初始路由器 url
【中文标题】在 iframe / 对象标签内运行时更新初始路由器 url【英文标题】:update initial router url when running inside iframe / object tags 【发布时间】:2020-02-12 07:36:54 【问题描述】:我目前正在容器/主 Vue 应用程序的对象标签内渲染 Vue 应用程序(iframe 也可以工作)。首先,我设置了一个文件服务器,为该容器或请求的子应用程序提供服务以在 div 内呈现。
为简单起见,我将只显示我的 Node/Express 服务器所需的路由
// serve the sub-app on demand
router.get('/subApps/:appName', function(req, res)
res.sendFile(path.resolve(__dirname, `../apps/$req.params.appName/index.html`);
);
// always render the app container if no sub-app was requested
router.get('*', function(req, res)
res.sendFile(path.resolve(__dirname, '../base/index.html'));
);
我的应用容器/主 Vue 应用位于 /apps/:appName
上呈现的视图文件中,请求该子应用并将其包装到对象标签中
document.getElementById("customAppContainer").innerHTML = `<object style="width: 100%; height:100%;" data="http://localhost:3000/subApps/$appKey"></object>`;
这种方法效果很好,但渲染的子应用使用启动 url http://localhost:3000/subApps/app-one
尽管它应该使用 url http://localhost:3000/apps/app-one
。当子应用加载路由器实例时,我必须将启动 url 从 iframe url 更改为浏览器 url(父)。
我考虑过用 history.replaceState
解决这个问题
const router = new Router( ... );
router.afterEach((to, from) =>
localStorage.subAppRouteUpdate = to.path;
);
if (window.location !== window.parent.location)
const browserUrl = top.location.href;
history.replaceState(null, null, browserUrl);
export default router;
我为什么要这样做?主应用的 App.vue 应该将子应用路由附加到浏览器 url。使用这种方法,可以在子应用程序内部导航时更新浏览器 url。我通过将子应用 url 存储到本地存储并在主应用端监听本地存储更改来实现这一点。所以 App.vue 文件使用了这段代码
<script>
export default
created()
window.addEventListener("storage", () =>
const fullRoute = this.$router.currentRoute.fullPath;
const routeSegments = fullRoute.split("/");
const appsIndex = routeSegments.indexOf("apps");
const newBaseUrlSegments = routeSegments.slice(0, appsIndex + 2);
const newBaseUrl = newBaseUrlSegments.join("/");
const subAppRoute = localStorage.subAppRouteUpdate;
const updatedUrl = newBaseUrl.concat(subAppRoute);
history.replaceState(null, null, updatedUrl);
);
;
</script>
在使用 IFrame 时启用路由。它几乎可以工作,这就是我得到的
不幸的是,当调用子应用的/
时,浏览器 url 会更新为
http://localhost:3000/apps/app-one/apps/app-one
虽然我期待
http://localhost:3000/apps/app-one/
复制:
我创建了一个repository 用于复制/测试。有人知道可能出了什么问题或如何修复该 url 更新?
更新:
我认为发生错误是因为在子应用的 router.js 中我正在触发此代码
if (window.location !== window.parent.location)
const browserUrl = top.location.href;
history.replaceState(null, null, browserUrl);
router.afterEach((to, from) =>
console.log( urlToAppend: to.path );
localStorage.subAppRouteUpdate = to.path;
);
replaceState 函数会将 IFrame url 从 /subApps/app-one
更新为正确的浏览器 url /apps/app-one
。不幸的是,这将触发 afterEach 事件,to.path
会导致/apps/app-one
,尽管它应该是/
。
如果 url 是 /apps/app-one/users/create
,那么在每个事件之后当然应该使用 /users/create
触发。
但我不知道如何解决这个第一个触发事件。
【问题讨论】:
【参考方案1】:这可能是一个有点老套的解决方案,但它对我有用。只需检查当前 url 路径是否不等于 to.path
以防事件被触发两次
router.afterEach((to, from) =>
console.log( urlToAppend: to.path );
if (router.currentRoute.path !== to.path)
localStorage.subAppRouteUpdate = to.path;
);
更新
在base/src/App.vue
中的存储事件侦听器中,在将子路由连接到基本路由之前,您不会检查可能的重复项。此修复程序应该会有所帮助
window.addEventListener("storage", () =>
const fullRoute = this.$router.currentRoute.fullPath;
const routeSegments = fullRoute.split("/");
const appsIndex = routeSegments.indexOf("apps");
const newBaseUrlSegments = routeSegments.slice(0, appsIndex + 2);
const newBaseUrl = newBaseUrlSegments.join("/");
const subAppRoute = localStorage.subAppRouteUpdate;
if (subAppRoute.startsWith(newBaseUrl))
history.replaceState(null, null, newBaseUrl);
else
const updatedUrl = newBaseUrl.concat(subAppRoute);
history.replaceState(null, null, updatedUrl);
);
router.afterEach
应该看起来像这样导航到在 app-one 路由器中定义的子路由:
router.afterEach((to, from) =>
const newPath = '/' + to.path.split('/').pop();
const matchingRoutes = router.options.routes.filter(r => r.path === newPath);
const isPathInRoutes = matchingRoutes.length > 0;
if (router.currentRoute.path !== newPath && isPathInRoutes)
router.push(newPath);
localStorage.subAppRouteUpdate = newPath;
else
localStorage.subAppRouteUpdate = to.path;
);
如果您希望在用户转到http://localhost:3000/apps/app-one
时默认呈现第一页,您可以检查输入的 url 的最后一部分是否等于子应用程序的基本路由(/app-one
),如果它确实导航到默认页面路线(/
):
router.afterEach((to, from) =>
let newPath = '/' + to.path.split('/').pop();
const matchingRoutes = router.options.routes.filter(r => r.path === newPath);
const isPathInRoutes = matchingRoutes.length > 0;
if (newPath === router.history.base || !isPathInRoutes)
newPath = '/';
if (router.currentRoute.path !== newPath)
router.push(newPath);
localStorage.subAppRouteUpdate = newPath;
else
localStorage.subAppRouteUpdate = to.path;
);
【讨论】:
所以如果你导航到App 1 - Page 2
,浏览器网址仍然是http://localhost:3000/apps/app-one
,但我希望http://localhost:3000/apps/app-one/two
你能检查我更新的答案是否按预期工作吗?
是的,你几乎明白了! :) 我遇到的最后一个问题是当调用此 url http://localhost:3000/apps/app-one
时,子应用程序不会呈现视图 One
。 http://localhost:3000/apps/app-one/two
相同,我希望它呈现 Two
.. :/
@ktad 我给了你赏金 :) 页面的渲染仍然缺失
我还更新了我的答案,以便在用户导航到http://localhost:3000/apps/app-one
时默认呈现第1页以上是关于在vue中使用iframe标签的主要内容,如果未能解决你的问题,请参考以下文章