【问题标题】:mount Vue apps into container of main Vue app将 Vue 应用程序挂载到主 Vue 应用程序的容器中
【发布时间】:2019-09-27 09:15:50
【问题描述】:

我想创建一个基本的 Vue 应用程序,提供登录、浏览侧边栏等基本功能。但导航栏项目必须是可互换的。我想创建代表这些导航栏项目的单独 Vue 应用程序。


基本思路: 应该提供一个 REST API 和一个基本容器(Vue 应用程序),它能够在特定的 div 元素中呈现其他 Vue 应用程序。这将允许其他人添加他们自己的前端应用程序并在他们愿意的情况下使用该 API。所以我只会提供一些基本的应用程序。主要思想是为非常模块化的管理系统创建一个即插即用系统。我将为该自定义应用程序提供一个注册过程,以便 API 知道该应用程序及其基本 url,并且我的基本应用程序可以获取所有这些应用程序。


基础应用设置

所以我的基础应用为这些自定义应用提供了路径

{
  path: '/app/*',
  component: CustomAppContainer,
},

并将渲染此视图

<template>
  <div id="customAppContainer">Render custom apps here</div>
</template>

我的导航栏可以提供链接/app/one 来导航和呈现该customAppContainer 中名为“one”的应用程序。


自定义应用设置

在定义我的路线时,我必须设置base url

export default new Router({
  base: '/one/',
  routes: [
    {
      path: '/',
      component: Home,
    },
  ],
});

但对于 ma​​in.js,我不确定如何设置它。我想我必须将其更新为类似

new Vue({
  router,
  render: h => h(CustomAppContainer),
}).$mount('#customAppContainer');

但显然这个应用不知道CustomAppContainer#customAppContainer


此外,当我只有一些 index.html 文件并希望将一个文件集成到另一个文件时,我正在考虑分发。那么如何部署基础应用程序,当用户想通过/app/myCustomApp 访问自定义应用程序时,我将自定义应用程序安装到customAppContainer 中?

一个类似的例子是Nextcloud

在开发新的 Vue 应用程序时,我可以将其作为独立应用程序运行。但是对于生产,我想从 dist 文件夹中获取文件并将它们放入 apps 目录中,当运行我的基本容器应用程序时,它会在启动时知道所有这些子应用程序。

如果您需要更多信息,请告诉我!

【问题讨论】:

  • 为什么不在私有 npm 包中创建所有功能,您可以简单地将其导入到新项目中?
  • 抱歉,我不想将该应用容器导入到新项目中。我想创建新项目并将它们的 index.html 附加到应用程序容器 index.html
  • 我认为 Balexandre 是对的。您有一个项目,并且该项目包含模块。您的模块是独立的 vue 应用程序,甚至可能包含一个带有路由和所有内容的索引页面,它们位于主项目中。因此,您的子应用容器听起来更像是一个您可以以我描述的模块形式注入依赖项的地方。模块是一个新项目。你说“将他们的 index.html 附加到应用程序容器 index.html”到底是什么意思?这听起来有点像您正在以您在其他地方学到的方式或格式思考,而 NPM 包是这里的解决方案。
  • 谢谢,但我真的不确定。也许一个新的子应用程序不是用 Vue、Angular 或 React 创建的,也许它只是一个 .html 文件,所以最好有一个 apps 目录并将所有这些应用程序放入该目录。然后我可以在 IFrame 中呈现每个应用程序,尽管使用 IFrame 将是一个糟糕的解决方案。使用 npm 包时,我必须将每个应用程序发布到 npm,也许其他应用程序使用 yarn 或类似的东西,因为他们只想用一些 Jquery 创建一个 .html 文件..

标签: javascript vue.js


【解决方案1】:

我终于用下面的方法让它工作了,也许这会对某人有所帮助。 非常感谢您的建议!


基础应用:

呈现所有子应用的基础应用有一个 CustomAppContainer 视图,可将子应用加载到 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>

我进一步将mode: 'history' 添加到路由器

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      component: Home
    },
    {
      path: '/apps/*',
      component: CustomAppContainer,
    }
  ]
})

我将该应用程序的构建文件放入我的生产目录中的一个名为 base

的文件夹中

文件服务器:

我创建了一个静态 Express 文件服务器,它始终为基础应用的 index.html 文件提供服务。但是我也可以请求子应用的index.html文件。

const express = require('express');
const path = require('path');
const fs = require('fs');
const cors = require('cors');
const app = express();
const router = express.Router();

app.use(cors());

app.use(express.static(path.resolve(__dirname, '../base')));

fs.readdirSync(path.resolve(__dirname, '../apps')).forEach(appName => {
    app.use(express.static(path.resolve(__dirname, `../apps/${appName}`)));
});

router.get('/subApps/:appName', function(req, res) {
    res.sendFile(path.resolve(__dirname, `../apps/${req.params.appName}/index.html`));
});

router.get('*', function(req, res) {
    res.sendFile(path.resolve(__dirname, '../base/index.html'));
});

app.use('/', router);

app.listen(3000, function() {
    console.log('Fileserver listening on port 3000');
});

自定义应用:

创建自定义应用时,我所要做的就是扩展 router 配置

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

并将 index.htmlma​​in.jsApp.vue 中的 #app ID 重命名为 #customApp

然后,我将该子应用的构建文件放入我的生产目录中的一个名为 apps 的文件夹中。


这允许我创建多个应用程序并将它们呈现到我的主应用程序容器的 div 容器中。子应用程序本身不必是 Vue 应用程序。我也可以使用 Jquery、Angular 或 React 创建新的应用程序,甚至只是一个普通的 .html 文件。

【讨论】:

    【解决方案2】:

    1

    Vue 不知道CustomAppContainer

    尝试添加import CustomAppContainer from "path/to/CustomAppContainer.vue"
    它必须在 .vue 文件中。


    2

    Vue 不知道#customAppContainer

    是的,该选择器必须在 index.html 中。你的在CustomAppContainer。 尝试将&lt;div id="#app"&gt;&lt;/div&gt; 之类的内容添加到index.html(通常在/public 文件夹中)并将.$mount('#customAppContainer'); 替换为.$mount('#app');


    3

    Vue 路由器需要&lt;router-view&gt; 标签。所以,试试这个标记:

    <!-- In template is all page -->
    <template>
      <!-- Some stuff as navigation... -->
      <nav>
        <!-- Router links - renders as "a" element -->
        <router-link to="/one">To /one</router-link>
        <!-- Or use standard tags - they're also good -->
        <a href="/two">To /two</a>
      </nav>
      <!-- In this component would be component chosen in router (Home.vue) -->
      <router-view/>
    </template>
    

    4

    Router.js 需要导入:

    import Home from "path/to/the/Home.vue"
    export default new Router({
      base: '/one/',
      routes: [
        {
          path: '/',
          component: Home,
        },
      ],
    });
    

    一切都好吗?

    【讨论】:

      猜你喜欢
      • 2020-09-06
      • 1970-01-01
      • 1970-01-01
      • 2018-01-28
      • 2021-08-19
      • 2017-08-03
      • 1970-01-01
      • 2021-04-11
      • 1970-01-01
      相关资源
      最近更新 更多