В настоящее время я визуализирую приложения Vue внутри тегов объектов (также может работать iframe) приложения Vue контейнера / мастера. Сначала я настраиваю файловый сервер, обслуживающий этот контейнер или запрошенное вспомогательное приложение для рендеринга внутри 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-адрес с URL-адреса iframe на 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>
, чтобы включить маршрутизацию при использовании IFrames. Это почти работает, вот что я получаю
К сожалению, бывает так, что при вызове /
подпрограммы URL браузера обновляется до
http://localhost:3000/apps/app-one/apps/app-one
хотя я ожидаю
http://localhost:3000/apps/app-one/
Воспроизведение:
Я создал репозиторий для воспроизведения / тестирования. Кто-нибудь знает, что может быть не так или как исправить это обновление URL-адреса?
Обновление:
Я думаю, что ошибка происходит, потому что в маршрутизаторе .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 обновит URL IFrame с /subApps/app-one
до правильного URL браузера /apps/app-one
. К сожалению, это вызовет событие afterEach и to.path
приведет к /apps/app-one
, хотя должно быть /
.
Если URL будет /apps/app-one/users/create
, то после каждого события должно срабатывать, конечно, /users/create
.
Но я так и не понял, как исправить это первое запущенное событие.