gpt4 book ai didi

javascript - 在 iframe/object 标签内运行时更新初始路由器 url

转载 作者:行者123 更新时间:2023-12-04 01:35:23 24 4
gpt4 key购买 nike

我目前正在容器/主 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 上呈现的 View 文件中,请求该子应用并将其包装到对象标签中
  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 存储到本地存储并在主应用端监听本地存储更改来实现这一点。所以 应用程序.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 时启用路由。它几乎可以工作,这就是我得到的

enter image description here

不幸的是,当调用 /子应用程序的浏览器 url 被更新到

http://localhost:3000/apps/app-one/apps/app-one



虽然我期待

http://localhost:3000/apps/app-one/



转载:

我创建了一个 repository用于复制/测试。有人知道可能出了什么问题或如何修复该网址更新吗?

更新:

我认为发生错误是因为在子应用程序的 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 函数将从 /subApps/app-one 更新 IFrame url到正确的浏览器 URL /apps/app-one .不幸的是,这将触发 afterEach 事件和 to.path结果 /apps/app-one虽然应该是 / .

如果网址是 /apps/app-one/users/create在每个事件之后应该触发 /users/create当然。

但我不知道如何解决这个第一个触发事件。

最佳答案

这可能是一个有点hacky的解决方案,但它对我有用。只需检查当前 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;
}
});

关于javascript - 在 iframe/object 标签内运行时更新初始路由器 url,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58397766/

24 4 0