【问题标题】:manipulate browser Url within embedded Vue app在嵌入式 Vue 应用程序中操作浏览器 URL
【发布时间】:2020-02-04 17:05:51
【问题描述】:

我目前将 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>

如果你想了解更多,请看这里

mount Vue apps into container of main Vue app

以及我自己对这个问题的回答

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

customAppContainerobject 标签内呈现的我的子应用有自己的路由,基本路由是

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

我可以浏览我的子应用并记录当前网址

<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();时得到的内容

【问题讨论】:

  • 所以你有一个(单个)vue 应用程序并且你想嵌入(远程获取)html? &lt;container id-".." v-html="dataHTML"&gt; 有什么问题,您将获取的数据放入 data.dataHTML 或类似的东西?
  • 非常感谢您的回复。我用这段代码hatebin.com/casjdcehrj 试过了,但仍然没有渲染子应用程序。仍然......纯 HTML 文件被渲染。
  • subApp 的内容是什么 - 你真的得到一些 text/data/html 吗?您可能会遇到 CORS 拒绝,
  • 嘿,这是我从服务器cdn.discordapp.com/attachments/165027329981153280/… 得到的响应,当我使用await response.text() 将其转换为文本时,我得到了cdn.discordapp.com/attachments/165027329981153280/…
  • @hrp8sfHxQ4 所以你真的想在 div 中嵌入一个完整的 html 文档? - 因为那是无效的 html,你可以使用 iframe(with src-attr) 代替。另一方面,我不确定您的app1 &gt; div &gt; remote-html(app2) 是否是正确的方法。您能否明确您真正想要解决的问题,以及为什么常规 async-components(in app1) 不够?您想嵌入您无法控制的应用程序吗?子应用与主应用有何不同,为什么要分开?

标签: javascript html vue.js


【解决方案1】:

我自己解决了这个问题。我采取了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。

【讨论】:

    猜你喜欢
    • 2012-02-07
    • 1970-01-01
    • 2016-07-01
    • 2010-10-30
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多