3
votes

If you've created a VueJS instance like this...

var app = new Vue({ el: '#app', components: {...} })

Is it possible to add components to this instance it's instantiated?

The reason I ask is that we have a multi-page app which stares a template. We want the instantiation of the Vue app to be in the shared template code but we want each page to use different components so for example the code on the contact page would be split between two files...

Master.js Contact.js

The contact.js file would need to tell the main app that it wanted to use the conract-form component, but that component is not used on other pages so we don't want to add it to the initial app declaration in the master.js

Any help would really be appreciated.

2
Sounds like you want vue-router. Or if not, maybe dynamic componentsthanksd
Thanks, but from that documentation dynamic components still require you to list the components you want to use in the main Vue instance when it is instantiated. I need to add them (or not) in a subsequent js file.jonhobbs
The documentation is lacking, but it's not required to list the components before instantiation. That's just the example they give. You can dynamically pass an object with a component definition via the v-bind:is="" directive at any time.thanksd
Cool, i'll try that, thanks. If it works please add it as an answer so I can mark is as correct :)jonhobbs
Hmm, I've just tried it without using dynamic components and it seems to work using normal components even if you don't specify which components you want to use when instantiating Vue. SHould this works? If it does then I think I have my answer.jonhobbs

2 Answers

1
votes

Thanks to @thanksd

It seems as though components only have to be registered when instantiating Vue if you want the registered "locally", which means you don't have to register them at all as long as the component code comes before Vue is instantiated.

So, my master template and master.js can contain this...

<div id="app">

    <header>Master header</header>

    <contact-page inline-template>
        Contents of contact page
    </contact-page>

    <footer>Master Footer</footer>

</div>

var app = new Vue({
  el: '#app'
})

Then, my contact.js can contain this....

Vue.component('contact-page', {
    ... Contact page specific code here...
});
1
votes

We had a similar trouble, with multiple pages, a layout et multiple components. Our system isn't a SPA. Each page reload. The page content is insert in a global layout with some global options by server code.

We have global components and some more especific by page, our solution is use window to catch Vue and initialize vue after charge the components by page.

IMPORTANT: follow this order declarations: windowVue / code specific for the page / startVue

EX:

layout file:

<!doctype html>
<html>
  <head>
    <script type="text/javascript" src="../js/windowVue.js"></script>
    <!-- all header content -->
    <!-- depend your system here call your js specific by page ex: productPage.js -->
    <script type="text/javascript" src="../js/productPage.js"></script>
  </head>

  <body>
    <div id="vueApp">
      <!-- Your page content-->  
    </div>
    <script type="text/javascript" src="../js/startVue.js"></script>
  </body>
</html>

windowVue.js

import Vue from 'vue';

window.Vue = Vue;

productPage.js

// Here two options declare the external components only 
import ComponentA from '../js/components/component-a.js';
import ComponentB from '../js/components/component-b.vue';

window.Vue.component('component-a', ComponentA)
window.Vue.component('component-b', ComponentB)

// Or if you use a page component with more logic and options you can declare here
// and include the other components as usual
window.Vue.component('product-page', {
  components: {
    ComponentA,
    ComponentB
  },
  // rest of the code as usual
})

startVue.js

import GlobalA from '../js/components/global-a.js';
import GlobalB from '../js/components/global-B.js';

new window.Vue({
  el:"#vueApp",
  delimiters: ['${', '}'],
  components: {
    GlobalA,
    GlobalB
  }
})

That's all now each page has their owns components and we have some shared components too.

some remarks:

  • build the 3 js part separately
  • Only windowVue.js use import Vue from 'vue' the rest use window.Vue.
  • .js files components are declared as an object.

component-a.js

import ComponentB from '../js/components/component-b.vue';
import ComponentC from '../js/components/component-c.vue';
import ComponentD from '../js/components/component-d.vue';

export default {
  name:'component-a',
  components: {
    ComponentB,
    ComponentC,
    ComponentD
  },
  data() {
    return {
      variableExample: 'example'
    }
  } // more of your Vue code
}