使用 Vue 3 在 InertiaJS 中定义全局组件

Posted

技术标签:

【中文标题】使用 Vue 3 在 InertiaJS 中定义全局组件【英文标题】:Define global component in InertiaJS with Vue 3 【发布时间】:2021-08-05 05:02:26 【问题描述】:

我正在尝试在 Laravel 8.38 - InertiaJS 0.8.4 上构建一个应用程序,我正在使用 Vue 3 作为我的前端堆栈。

我有多个布局需要全局注册为Vue 组件,以便我可以在任何地方的应用程序中使用它。我做不到,我的代码:

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);

在页面内部我试图调用这个布局组件:

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

无法获取,控制台中没有错误。

【问题讨论】:

您注册了一个app-market 组件,但您的标记使用了app-market-layout 【参考方案1】:

我有 2 个用于后端(管理面板)和前端(网站)的布局,实现如下。使用惯性默认中间件文件。

项目/app/Http/Middleware/HandleInertiaRequests.php

class HandleInertiaRequests extends Middleware

    protected $rootView = 'app';

    public function rootView(Request $request)
    
        if ($request->segment(1) == '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>

【讨论】:

【参考方案2】:

在 Inertia JS 中,全局导入组件与使用普通 Vue 配置相同。

在您的 app.js 文件中,您需要导入组件(内联或文件顶部),然后在挂载 vue 实例之前添加组件。 You can either do this as a mixin, or as a component.

因此,在您的情况下,配置应如下所示:

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);

然后,在您的模板中,您可以像这样使用组件:

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

我在您的原始帖子中注意到您正在尝试将该组件用作应用市场布局。如果您打算这样做,则必须导入具有该名称的组件。

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);

然后在你的模板中:

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

【讨论】:

以上是关于使用 Vue 3 在 InertiaJS 中定义全局组件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel InertiaJS 中使用 VueJS 配置 Tailwind + Postcss

如何使用 Laravel 8、Inertia.js 和 Vue3 定义全局变量?

使用 Inertia JS 从嵌套布局中控制 Vue 组件

如何使用 Inertia Js、Vue 和 Laravel 重新加载持久布局或观看道具

多参数 InertiaJS 路由

InertiaJS 在验证错误后保留表单数据