首页 > 解决方案 > 在嵌入式 Vue 应用程序中操作浏览器 URL

问题描述

我目前将 Vue 应用程序渲染为 Vue 应用程序。我通过将子应用的 index.html 文件嵌入到主应用的 div 容器中来实现这一点。

<template>
  <div id="customAppContainer"></div>
</template>

<script>
export default {
  mounted() {
    this.updateCustomAppContainer();
  },
  methods: {
    updateCustomAppContainer() {
      const fullRoute = this.$router.currentRoute.fullPath;
      const routeSegments = fullRoute.split("/");
      const appsIndex = routeSegments.indexOf("apps");
      const appKey = routeSegments[appsIndex + 1];

      document.getElementById(
        "customAppContainer"
      ).innerHTML = `<object style="width: 100%; height:100%;" data="http://localhost:3000/subApps/${appKey}"></object>`;
    }
  },
  watch: {
    $route(to, from) {
      this.updateCustomAppContainer();
    }
  }
};
</script>

如果您想了解更多相关信息,请查看此处

将 Vue 应用程序挂载到主 Vue 应用程序的容器中

和我自己对这个问题的回答

https://stackoverflow.com/a/58265830/9945420

object我在标签内呈现的子应用程序customAppContainer有它自己的路由,基本路由将是

export default new Router({
    base: '/my-first-custom-app/',
    mode: 'history',
    routes: [
        {
            path: '/',
            component: PageOne,
        },
        {
            path: '/two',
            component: PageTwo,
        },
    ],
});

我可以浏览我的子应用程序并记录当前的 url

<script>
export default {
  created() {
    console.log(this.$router.currentRoute.fullPath);
  }
};
</script>

在第一条路线上我得到/了,在第二条路线上我得到了/two。这是对的。但是在浏览子应用程序时,浏览器 URL 永远不会改变。调用localhost:3000/apps/my-first-custom-app/two文件服务器时index.html,无法转发到/two.

是否可以转发到正确的路线?并在浏览子应用程序时操纵浏览器 URL?


更新:

我试图删除对象标签,因为它们似乎创建了一个黑盒。我在这里找到了另一种方法

https://stackoverflow.com/a/55209788/9945420

更新的代码应该是

<template>
  <div id="customAppContainer"></div>
</template>

<script>
export default {
  async mounted() {
    await this.updateCustomAppContainer();
  },
  methods: {
    async updateCustomAppContainer() {
      const fullRoute = this.$router.currentRoute.fullPath;
      const routeSegments = fullRoute.split("/");
      const appsIndex = routeSegments.indexOf("apps");
      const appKey = routeSegments[appsIndex + 1];

      // document.getElementById(
      //   "customAppContainer"
      // ).innerHTML = `<object style="width: 100%; height:100%;" data="http://localhost:3000/subApps/${appKey}"></object>`;

      const response = await fetch(`http://localhost:3000/subApps/${appKey}`);
      const htmlContent = await response.text();
      document.getElementById("customAppContainer").innerHTML = htmlContent;
    }
  },
  watch: {
    async $route(to, from) {
      await this.updateCustomAppContainer();
    }
  }
};
</script>

此代码适用于纯 HTML 文件(无 Vue 应用程序),但当我想嵌入分布式 Vue 应用程序时,此应用程序不会呈现。


极简再现

我创建了一个用于复制的简约存储库。

https://github.com/byteCrunsher/temp-reproduction

开发目录包含静态文件服务器、应该渲染 Vue 应用程序的基本 Vue 应用程序和应用程序本身。请记住,第一个应用程序是 Vue 应用程序,第二个应用程序只是一个基本的 HTML 文件。

生产目录包含文件服务器、分布式 Vue 应用程序和 html 文件。只需从生产目录运行静态文件服务器,然后转到http://localhost:3000您应该看到我当前的工作。


更新

当我使用 vue 指令v-html并将响应存储到数据属性 ( https://hatebin.com/casjdcehrj ) 时,我会从服务器获得此响应

在此处输入图像描述

这是我使用时得到的内容await response.text();

在此处输入图像描述

标签: javascripthtmlvue.js

解决方案


我只是自己解决了这个问题。我采用了 IFrame / object 标签方式

document.getElementById(
    "customAppContainer"
  ).innerHTML = `<object style="width: 100%; height:100%;" data="http://localhost:3000/subApps/${appKey}"></object>`;

这种方式的缺点是将嵌入式应用程序与主应用程序隔离开来。但是可以通过 localStorage 进行通信。subApp 扩展了它的 router.js 文件

router.afterEach((to, from) => {
    localStorage.subAppRouteUpdate = to.path;
});

每当我浏览该嵌入式应用程序时都会触发此事件,并将更新的 url 存储到 localStorage。基础应用程序可以监听该存储更改。在 App.vue 中,它添加了一个事件监听器并将 subApp url 附加到浏览器 url

<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>

使用这种方法,我目前能够浏览我的容器化子应用程序,并且仍然可以更新浏览器 url。


推荐阅读