如何 show/hide @foreach 语句

How to show/hide @foreach statement

我有一个 Vuejs 3 下拉可重用组件。我的问题是 @foreach 语句在组件加载之前运行,因此它会导致 foreach 结果闪烁,这在刷新或加载页面时非常难看。

演示请查看此 gif:

我在 blade 中的组件:


<Dropdown title="{{ isset($currentCategory) ? ucwords($currentCategory->name) : 'Categories' }}">

    <Dropdowncontent>

        <Dropdownitems href="/">
            All
        </Dropdownitems>

        <div>
            @foreach ($categories as $category)
                <Dropdownitems
                    href="/?category={{ $category->slug }}&{{ http_build_query(request()->except('category')) }}"
                    class="{{ isset($currentCategory) && $currentCategory->is($category) ? ' selectedCategoryItem' : '' }}">
                    {{ $category->name }}
                </Dropdownitems>
            @endforeach
        </div>

    </Dropdowncontent>

</Dropdown>

我添加了一个 div 来包含 @foreach 语句,但我不知道从这里可以做什么。我不想使用 alpineJS,因为它会破坏使用 Vue 的目的(我猜?)。

我只需要一种方法来仅显示此 div 或 @foreach 语句(如果组件已完全加载或按下按钮或类似情况)。有什么想法吗?

-- 编辑--

我试图在我的 'dropdownitems' vue 组件中隐藏链接并将默认值设置为 false。链接现在已隐藏,但 blade @foreach 语句在加载组件之前将结果作为文本回显:

<template>
    <a v-if="showLinks" href="" class="demogard categoryItems">
        <slot />
    </a>
</template>

<script>
export default {
    name: "Dropdownitems",
    setup() {
        const showLinks = false;

        return {
            showLinks,
        };
    },
};
</script>

<style></style>

这是一个显示结果的 gif:

-- 编辑--

这是我的下拉组件:

<template>
    <div
        class="relative"
        v-click-outside="onClickOutside"
        @click="showCategories"
    >
        <slot name="toggler">
            <button
                class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9 text-sm font-semibold lg:inline-flex lg:w-32"
            >
                {{ title }}
            </button>
        </slot>

        <slot />
    </div>
</template>

<script>
import vClickOutside from "click-outside-vue3";
import { ref, onMounted, provide } from "vue";
export default {
    name: "Dropdown",
    props: ["title"],
    directives: {
        clickOutside: vClickOutside.directive,
    },
    setup() {
        const sharedState = ref(false);

        const showCategories = () => {
            sharedState.value = !sharedState.value;
        };

        const onClickOutside = (event) => {
            sharedState.value = false;
        };

        provide("sharedState", sharedState);


        return {
            sharedState,
            showCategories,
            onClickOutside,
        };
    },
};
</script>

<style></style>

尝试使用@if 指令:

Conditional Rendering

来自文档:

<button @click="awesome = !awesome">Toggle</button>

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no </h1>

如示例所示,它有条件地呈现“h1”标签并尊重“awesome”变量。 在这种情况下,我将设置一个默认值“false”,我将在安装的钩子中将它变成“true”:

Lifecycle

作为你的问题,我认为你必须在下拉组件上添加 if condition

你的下拉组件应该是这样的

#dropdown.vue
<template>
    <div class="dropdown">
        <div @click="show = !show">{{title}}</div>
        
        <div v-if="show">
            <slot />
        </div>
    </div>
</template>
<script>
import { ref } from "vue";
export default {
  props: ["title"],
  setup(props) {
    const show = ref(false);
    return {
      show,
    };
  },
};
</script>

Demo

---- 编辑 ----

#dropdown.vue
<template>
    <div
        class="relative"
        v-click-outside="sharedState = false"
    >
        <slot name="toggler">
            <button
                class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9 text-sm font-semibold lg:inline-flex lg:w-32"
                @click="sharedState = !sharedState"
            >
                {{ title }}
            </button>
        </slot>
        <div v-if="sharedState">
            <slot />
        </div>
    </div>
</template>

<script>
import vClickOutside from "click-outside-vue3";
import { ref, onMounted, provide } from "vue";
export default {
    name: "Dropdown",
    props: ["title"],
    directives: {
        clickOutside: vClickOutside.directive,
    },
    setup() {
        const sharedState = ref(false);

        // const showCategories = () => {
        //     sharedState.value = !sharedState.value;
        // };

        // const onClickOutside = (event) => {
        //     sharedState.value = false;
        // };

        provide("sharedState", sharedState);

        return {
            sharedState,
            //showCategories,
            //onClickOutside,
        };
    },
};
</script>

<style></style>

无法在 PHP 之前加载 Vue,因为您的网页仅在从服务器收到完整的 PHP 代码后才会显示。因此,如果我们在可重用的 Vue 组件中使用它们,我们永远无法阻止 PHP 或 HTML 闪烁。

我做的解决方案是简单地将 foreach 循环的值作为 prop 传递给 Vue 组件,以便它从那里显示,而不是从我的 blade 文件。

这是我在将类别名称的值作为 prop 传递给我的 Vue 组件后在 blade 中的代码。

<Dropdown title="{{ isset($currentCategory) ? ucwords($currentCategory->name) : 'Categories' }}">

    <Dropdowncontent>

        <Dropdownitems href="/" category="All"></Dropdownitems>

        @foreach ($categories as $category)
            <Dropdownitems 
                category="{{ $category->name }}"
                href="/?category={{ $category->slug }}&{{ http_build_query(request()->except('category')) }}"
                class="{{ isset($currentCategory) && $currentCategory->is($category) ? ' selectedCategoryItem' : '' }}">
            </Dropdownitems>
        @endforeach

    </Dropdowncontent>

</Dropdown>

这是我从那里显示的 Vue 下拉项目组件:

<template>
    <a href="" class="demogard categoryItems">
        <slot>{{ category }}</slot>
    </a>
</template>

<script>
export default {
    name: "Dropdownitems",
    props: ["category"],
};
</script>

<style></style>