mount Vue apps into container of main Vue app

后端 未结 2 1169
走了就别回头了
走了就别回头了 2021-01-12 04:09

I would like to create a base Vue app providing basic functionality like signing in, navigating through a sidebar etc. But the navbar items have to be interchangeable. I wan

相关标签:
2条回答
  • 2021-01-12 04:22

    I finally got it working with the following approach and maybe this will help someone. Suggestions highly appreciated!


    Base App:

    The base app which renderes all the sub-apps has a CustomAppContainer view that loads the sub-apps into a div container.

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

    Further I added mode: 'history' to the router.

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

    I put the build files of that app into my production directory in a folder called base


    File Server:

    I created a static Express file server that always serves the index.html file of the base app. But I can request the index.html file of the sub-app too.

    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');
    });
    

    Custom App:

    When creating custom apps all I have to do is to extend the router config

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

    and rename the #app ID to #customApp in the index.html, main.js and App.vue.

    Further I put the build files of that sub-app into my production directory in a folder called apps.


    This allows me to create mulitple apps and render them into a div container of my main app container. The sub-app itself doesn't have to be a Vue app. I can create new apps with Jquery, Angular or React too, or even just a plain .html file.

    0 讨论(0)
  • 2021-01-12 04:35

    1

    Vue does not know CustomAppContainer

    Try to add import CustomAppContainer from "path/to/CustomAppContainer.vue"
    It must be in .vue file.


    2

    Vue does not know #customAppContainer

    Yes, that selector must be in index.html. Yours is in CustomAppContainer. Try to add to index.html (usually in /public folder) something like <div id="#app"></div> and replace .$mount('#customAppContainer'); with .$mount('#app');


    3

    Vue router needs <router-view> tag. So, try this markup:

    <!-- 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 needs import:

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

    All is good?

    0 讨论(0)
提交回复
热议问题