繁体   English   中英

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

[英]How can I reload a persistent layout or watch props with InertiaJs, Vue & Laravel

我有一个带有 InertiaJs 和 Vue3 的 Laravel 项目。 我有一个导航作为持久布局,按预期工作。

我在Users 和 Organizers之间有ManyToMany关系。 而我的知识库文章 model属于组织者 每个用户只能访问属于该用户所属组织者的文章。 知识库文章 model 有一条嵌套路线

Route::resource('organizers.knowledgebase_articles', KnowledgebaseArticleController::class)
        ->middleware(['permission:view_all_knowledgebase_articles|view_knowledgebase_articles']);

例如:test.com/organizers/1/konowledgebase_articles

并且用户可以更改当前的组织者,这样他们就只能看到他们当前组织者的文章,这是一个帖子路由,重定向回仪表板

// OrganizerController
public function change_organizer($organizer_id)
    {
        $organizer = Organizer::findOrFail($organizer_id);
        abort_if(!$organizer->users()->where('users.id', auth()->user()->id)->exists(), 403);

        $user = auth()->user();
        $user->currentOrganizer()->associate($organizer_id);
        $user->save();

        session(['organizer_id' => $organizer->id, 'organizer_name' => $organizer->name]);

        return redirect()->route('organizer.dashboard');
    }

// PersistentLayout.vue
function changeOrganizer(organizer_id) {
    Inertia.post(route('organizer.change', { id: organizer_id }));
}

当前组织者作为页面道具共享。

我的导航有一个固定的布局

我的问题是,在更改当前组织者之后,导航链接与以前保持不变,并且组织者 ID 不会在导航链接中更新。

因此,尽管我从 organizer_id 1 更改为 2,并且页面属性也更改为 2,但导航链接仍保留在 test.com/organizers/1/knowledgebase_articles

我的问题是:我能否以某种方式触发页面的完全重新加载,包括持久布局,或者我将如何解决该问题?

这是持久布局的一部分

<template>
                        <Menu as="div" class="ml-3 relative" v-if="props.auth.organizers">
                            <div>
                                <MenuButton class="max-w-xs bg-white flex items-center text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                                    <span>{{ props.current_organizer.organizer_name }}</span>
                                </MenuButton>
                            </div>
                            <transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
                                <MenuItems class="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
                                    <MenuItem v-slot="{ active }" v-for="organizer in props.auth.organizers">
                                        <Link
                                            @click.prevent="changeOrganizer(organizer.id)"
                                            as="button">
                                            {{ organizer.name }}
                                        </Link>
                                    </MenuItem>
                                </MenuItems>
                            </transition>
                        </Menu>
</template>

<script setup>
import {ref, watch} from 'vue'

let props = defineProps({
    auth: Object,
    current_organizer: Object
});

let navigation = [
    { name: 'Dashboard', href: route('dashboard'), icon: HomeIcon, type: 'parent' },
    { name: 'Organizers', href: route('organizers.index'), icon: BriefcaseIcon, type: 'parent' },
    { name: 'Knowledgebase', href: route('organizers.knowledgebase_articles.index', {organizer: props.current_organizer.organizer_id}), icon: InboxIcon, type: 'parent' },
    { name: 'Articles', href: route('organizers.knowledgebase_articles.index', {organizer: props.current_organizer.organizer_id}), icon: null, type: 'child' },
    { name: 'Categories', href: route('organizers.knowledgebase_categories.index', {organizer: props.current_organizer.organizer_id}), icon: null, type: 'child' },

];

function changeOrganizer(organizer_id) {
    Inertia.post(route('organizer.change', { id: organizer_id }));
}
</script>

非常感谢!

抱歉回复晚了。 我正在这样做。

<template>

 <your-menu-component :key="currentRoute"/>

</template>

<script>

export default {
computed: {
    currentRoute() {
        return location.pathname.substr(1)
    },
  },
}

当当前路由更改菜单组件的键发生更改时。 它将触发重新加载导航

我建议使用 state 解决方案。 Vue3应用目前推荐的state解决方案是Pinia

它很容易安装到您现有的应用程序中。 安装后,您可以为您的组织/租户创建一个商店 state。

状态/tenancyStore.js

import { defineStore } from "pinia";

export default defineStore('tenancy', {
    state: () => {
        return {
            currentOrganizer: null,
        }
    }
});

接下来,在您的页面组件中,您将使用通过页面道具收到的组织者更新商店。 重要的是要确保当 prop 更改时,更改会传播到商店。 你可以通过观看道具来做到这一点。

<script>
import useTenancyStore from './state/tenancyStore';

export default {
    props: {
        currentOrganizer: Object
    },
    setup (props) {
        const tenancyStore = useTenancyStore();

        watchEffect(() => {
            tenancyStore.currentOrganizer = props.currentOrganizer;
        });
    },
}
</script>

<template>
    <section>
        Hi, I'm a page!
    </section>
</template>

最后,在您的导航组件中,您可以再次使用刚刚创建的 state 商店中的信息。

<script>
import useTenancyStore from './state/tenancyStore';
import { watchEffect } from "vue";

export default {
    setup (props) {
        const tenancyStore = useTenancyStore();

        return { tenancyStore }
    },
}
</script>

<template>
    <nav>
        {{ tenancyStore.currentOrganizer.name }}
    </nav>
</template>

或者,您可以在 currentOrganizer 更改时发出和捕获事件。 我建议不要采用这种方法,因为事情很快就会变得一团糟。 State 商店已经达到了非常易于实施和易于维护的地步。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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