Vue 3 introduced a change where creating an app using createApp
will result in a standalone Vue App instance. In order to add a global component, you need to add it to the app
object created from createApp
. Here's how you can do that:
const app = createApp({});
app.component('my-component-name', MyComponent)
app.mount("#app");
However, managing a lot of components directly in the main.ts
file can become messy. To address this issue, you can create a separate file like 'globalComponents.ts' and import the components there:
Your current globalComponents.ts
import { createApp } from "vue"
const app = createApp({})
// Forms
app.component("ui-input", () => import("@/components/core/ui/Input.vue"))
The Issue
An error in the approach above is that another app
instance is being created using createApp
, which goes against the requirement of having all global components within the same instance.
Solution
To overcome this problem, pass the existing app
instance from 'main-ts' to 'globalComponents.ts'. This way, both files share the same instance:
globalComponents.ts
import { App } from "vue";
// register components
export const registerComponents = (app: App): void => {
app.component("ui-input", () => import("@/components/core/ui/Input.vue"));
}
You can then call the registerComponents
function in 'main.ts' as follows:
main.ts
const app = createApp(App)
.use(store)
.use(router);
registerComponents(app);
app.mount("#app");
If you encounter the error message "[Vue warn]: Invalid VNode type: undefined (undefined)", refer to the official documentation on defining async components in Vue 3. To resolve this error, wrap your import
statement with defineAsyncComponent
:
globalComponents.ts
import { defineAsyncComponent } from "vue";
// register components
export const registerComponents = (app) => {
app.component(
"ui-input",
defineAsyncComponent(() => import("@/components/Input.vue"))
);
};