Vue.component alternative in Vue 3
Asked Answered
T

2

5

I'm using Vue with Laravel Mix. In Vue version 2, I was able to do this:

1. resources/js/app.js:

import Vue from 'vue';
import MyComponent from './MyComponent';
Vue.component('my-component', MyComponent);

2. resources/js/MyComponent.vue:

<template>
    <p>{{message}}</p>
</template>
<script>
export default {
    name: "MyComponent",
    props: ['message']
}
</script>

As this Vue 2 document instructed. I know it was not the best practice, but it was the only approach that I have to conveniently pass data from Laravel's Blade template to the component, such as below:

3. anyview.blade.php:
<my-component :message='message' id='app'></my-component>
<script src='public/js/app.js'><script> //include compiled resources/js/app.js
<script>
    let app = new Vue({
        el: '#app',
        data() {
            return {
                message: 'Hello World';
            }
        }
    })
</script>

In real case, 'Hello World' would be replaced with something like:

message: {{$myMessaGe}}

But since Vue 3, Vue.component is no longer a thing because Vue object is not a default export.

This work flow (1-2-3) has been seamlessly fine, so returning to Vue2 is the last unhappy choice :(


I have tried to work around, just changing Vue.component with the new createApp:

4. resources/js/app.js:

import { createApp } from 'vue';
import MyComponent from './MyComponent';
createApp({
    components: {
        MyComponent,
    }
}).mount('#app');

But instead of adding MyComponent to current instance, it just creates a new one as depicted below - meaning that the prop message can't be passed through.

enter image description here


My question is: Is there any alternative API or workaround to compensate the loss of Vue.component()?

Taneshatang answered 23/3, 2022 at 15:36 Comment(0)
R
6

I have only worked with Vue3 so far but what I understand from the documentation is that the components in Vue3 are not that different from components in Vue2.

Try this solution:

import { createApp } from 'vue';
import MyComponent from './MyComponent';

const app = createApp({});

app
   .component('MyComponent', MyComponent)
   .mount('#app');

You can find more about this in the Vue3 docs.

Reason answered 23/3, 2022 at 17:39 Comment(5)
It just creates another instance as I depicted in (4). Which mean prop value can't be passed throughSchooling
What is you frontpage? And is MyComponent part of your frontpage? I have a SPA with 'App.vue' as my frontpage which only consists of the HTML-structure and all the components but no content. This works for me: import {createApp} from "vue"; import App from "./App.vue"; import MyComponent from "./MyComponent.vue"; createApp(App).component("MyComponent", MyComponent).mount("#app");Reason
My front page is rendered by PHP and I was only intended to use Vue as a component, not for an entire SPA, and I want to pass data from PHP view to the component via props. If I understand correctly, you are moving all component to SFC, which definitely works, if so, how can you passs PHP myMessage to Vue?Schooling
And yes, HTML structures do get rendered, but since props is not passed, there is no contentSchooling
did you find a solution to this please?Gynarchy
T
0

This is quite an old post. Although I'm not sure if it is the best practice, to overcome this, what I had done was instead of printing value (directly from Blade template) to the main App component, I just passed the value to the destination, or child components. Passing value through the component trees is not always the best thing to do.

3. anyview.blade.php:
<div id='app'>
    <my-component message='{{$myMessage}}'></my-component>
    <my-other-component foo='{{$bar}}'></my-other-component>
</div>

Any other piece of code are basically kept the same. The key is to pass the value to the component which needs. The thing I was doing wrong was trying to pass props value directly onto the parent most App component from a PHP variable in Blade templates

Taneshatang answered 23/5 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.