简体   繁体   中英

Define global component in InertiaJS with Vue 3

I'm trying to build an application on Laravel 8.38 - InertiaJS 0.8.4 I'm using Vue 3 as my frontend stack.

I've multiple layouts which I need to register globally as Vue Component, so that I can use it in my application anywhere. I'm unable to do so, my code:

import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';

const el = document.getElementById('app');

const app = createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: (name) => require(`./../Pages/${name}`).default,
        }),
})
    .mixin({ methods: { route } })
    .use(InertiaPlugin);

app.component('app-market', () => import('./../layouts/AppMarketLayout')); //trying to import layout

app.mount(el);

And inside the page I'm trying to call this layout component:

<template>
    <div>
        <app-market-layout></app-market-layout>
    </div>
</template>

Unable to fetch, no errors in console.

I was having 2 layouts for backend(admin-panel) and frontend(website), achieved as follows. Using inertia default middleware file.

project/app/Http/Middleware/HandleInertiaRequests.php

class HandleInertiaRequests extends Middleware
{
    protected $rootView = 'app';

    public function rootView(Request $request)
    {
        if ($request->segments()[0] == 'admin') {
            return 'admin';
        }

        return parent::rootView($request);
    }

    public function version(Request $request)
    {
        return parent::version($request);
    }

    public function share(Request $request)
    {
        return array_merge(parent::share($request), [
            //
        ]);
    }
}

project/resources/js/Shared/Frontend/Layouts/Layout.vue

<template>

    <Header />

    <slot />

    <Footer />

</template>

<script>
    import Header from '../Partials/Header'
    import Footer from '../Partials/Footer'
    export default {
        components: {
            Header,
            Footer
        },

        name: "FrontendLayout"
    }
</script>

project/resources/js/Pages/Frontend/Auth/Login.vue

<template>
    ...
</template>

<script>
    import Layout from '@/js/Shared/Frontend/Layouts/Layout';
    export default {
        
        layout: Layout,

        metaInfo: { title: 'Login' },

        data() {
            return {
                form: this.$inertia.form({
                    'email': '',
                    'password': '',
                    'remember': false
                })
            }
        },

        methods: {
            submit() {
                this.form.post(route('login.store'))
            }
        }
    }
</script>

In Inertia JS, importing components globally is a little different than using a normal Vue configuration.

In your app.js file, you need to import the component(either inline or at the top of the file), then add the component before mounting the vue instance.

So, in your case, the configuration should look like the below:

import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';

//Import the component:
import AppMarket from "./../layouts/AppMarketLayout"; 

const el = document.getElementById('app');

const app = createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: (name) => require(`./../Pages/${name}`).default,
        }),
})
    .mixin({ methods: { route } })
    .mixin({ components: { AppMarket } }) // << Then tell the inertia 
             // instance to use the component. 
             // You can also add this to the other mixin declaration
    .use(InertiaPlugin)
    .mount(el);

Then, in your template, you can use the component like this:

<template>
    <app-market>
    </app-market>
</template>

I noticed in your original post you are trying to use the component as app-market-layout. You must import the component with that name if you plan to do that.

The configuration would look like this in app.js:

import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '@inertiajs/inertia-vue3';

//Import the component: Notice the component name change.
import AppMarketLayout from "./../layouts/AppMarketLayout"; 

const el = document.getElementById('app');

const app = createApp({
    render: () =>
        h(InertiaApp, {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: (name) => require(`./../Pages/${name}`).default,
        }),
})
    .mixin({ methods: { route } })
    .mixin({ components: { AppMarketLayout } }) // << Here the component name has Layout
    .use(InertiaPlugin)
   
    .mount(el);

Then in your template:

<template>
    <app-market-layout>
    </app-market-layout>
</template>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM