Javascript 在iframe/object标记内运行时更新初始路由器url
我目前正在容器/主Vue应用程序的对象标记(iframe也可以工作)内呈现Vue应用程序。首先,我设置了一个文件服务器,为该容器或请求的子应用提供服务,以便在div中呈现 为了简单起见,我将只显示Node/Express服务器所需的路由Javascript 在iframe/object标记内运行时更新初始路由器url,javascript,html,node.js,express,vue.js,Javascript,Html,Node.js,Express,Vue.js,我目前正在容器/主Vue应用程序的对象标记(iframe也可以工作)内呈现Vue应用程序。首先,我设置了一个文件服务器,为该容器或请求的子应用提供服务,以便在div中呈现 为了简单起见,我将只显示Node/Express服务器所需的路由 // serve the sub-app on demand router.get('/subApps/:appName', function(req, res) { res.sendFile(path.resolve(__dirname, `../ap
// 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'));
});
My app container/master Vue app位于/apps/:appName
上呈现的视图文件中,请求该子应用并将其包装到对象标记中
document.getElementById("customAppContainer").innerHTML = `<object style="width: 100%; height:100%;" data="http://localhost:3000/subApps/${appKey}"></object>`;
我为什么要这样做?主应用程序的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>
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
但是我没有弄清楚如何修复这个第一次触发的事件。这可能是一个有点黑客的解决方案,但对我来说很有效。只要检查当前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(“存储”),()=>{
const fullRoute=此。$router.currentRoute.fullPath;
const routeSegments=完整路由分割(“/”);
const appsIndex=routeSegments.indexOf(“应用”);
const newBaseUrlSegments=routeSegments.slice(0,appsIndex+2);
const newBaseUrl=newBaseUrlSegments.join(“/”);
const subAppRoute=localStorage.subAppRouteUpdate;
if(子路径开始与(newBaseUrl)){
replaceState(null,null,newBaseUrl);
}否则{
const updatedUrl=newBaseUrl.concat(子路径);
replaceState(null,null,updateUrl);
}
});
和<代码>路由器。每次<代码>后,应如下所示导航到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-一个
您可以检查输入url的最后一部分是否等于子应用程序基本路由(/app one
),以及它是否导航到默认页面路由(/
):
router.afterEach((to,from)=>{
让newPath='/'+到.path.split('/').pop();
const matchingRoutes=router.options.routes.filter(r=>r.path==newPath);
const isPathInRoutes=matchingRoutes.length>0;
if(newPath==router.history.base | |!isPathInRoutes){
新路径='/';
}
if(router.currentRoute.path!==newPath){
路由器推送(newPath);
localStorage.subAppRouteUpdate=newPath;
}否则{
localStorage.subAppRouteUpdate=to.path;
}
});
因此,如果您导航到应用程序1-第2页
浏览器url仍然是http://localhost:3000/apps/app-一个
但我希望http://localhost:3000/apps/app-一/二
你能检查一下我更新的答案是否按预期工作吗?是的,你几乎做到了!:)我遇到的最后一个问题是调用此urlhttp://localhost:3000/apps/app-一个
子应用程序不会呈现视图一个。http://localhost:3000/apps/app-一个/两个
我希望它能呈现两个。:/@ktad我奖赏你:)页面的呈现仍然丢失,但我也更新了我的答案,因此当用户导航到http://localhost:3000/apps/app-一个
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;
}
});