Cananau Cristian
Cananau Cristian

Reputation: 456

How to pass createApp in Vue 3 among the app?

I'm migrating from Vue 2 to Vue 3. In Vue 2, it's possible to register a component globally like this: main.js

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

A global registration of a component: my-component.js

Vue.component('my-component', {
  template: '<div>Hi!</div>'
})

I'm using Webpack for import Single File Components in other components, and then i'm bundling it in one file. With Vue 2, that was easy because Vue instance was globally registered. Now with Vue 3, that doesn't work any more because of Vue.createApp({}).mount('#app'). I was trying to do something like this: main.js

const app = createApp({});

export const app;

And in: my-component.js

import { app } from './main.js';

app.component('my-component', {
  template: '<div>Hi!</div>'
})

And at the end: close-app.js

import { app } from './main.js';

app.mount('#app');

And in: index.html

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
<script type="application/javascript" src="my-component.js"></script>
<div id="app">
    <my-component></my-component>
</div>
<script type="application/javascript" src="close-app.js"></script>

I'm importing the app because of Webpack. Webpack is bundling it in self-invoking functions, but that doesn't work. I know there is a way to declare it globally like this: window.app = app;, but that's not a good idea. Can someone help me with that?

Upvotes: 2

Views: 6295

Answers (1)

tony19
tony19

Reputation: 138196

Components Webpacks

Since Vue 3 component registration has to be invoked on an app instance, and you're importing each component Webpack individually, I don't think you can avoid globals. Using a global app instance (window.app) in your components might be the easiest solution, especially if you want to minimize the changes.

Alternatively, you could build the components as UMD modules, where the component definition is exported as a global, import the UMD module with the <script> tag (as you're already doing), and call app.component() for each of them:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>

<!-- sets MyComponent global -->
<script type="application/javascript" src="./my-component.umd.js"></script>

<div id="app">
  <my-component></my-component>
</div>

<script>
const app = Vue.createApp({})
app.component(MyComponent.name, MyComponent)
app.mount('#app')
</script>

Component Module Scripts

In main.js, use createApp from the global Vue that you've imported in the <script> tag:

export const app = Vue.createApp({})

Then import your scripts as modules with <script type="module">:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
<script type="module" src="./my-component.js"></script>
<div id="app">
  <my-component></my-component>
</div>
<script type="module" src="./close-app.js"></script>

demo

Upvotes: 4

Related Questions