Vue 插槽在插槽 v-if 语句启动之前加载异步组件

Posted

技术标签:

【中文标题】Vue 插槽在插槽 v-if 语句启动之前加载异步组件【英文标题】:Vue slot loads async component before the slot v-if statement kicks in 【发布时间】:2018-11-18 05:44:35 【问题描述】:

我遇到了一个问题,即在实际显示之前加载了同步组件 javascript

使用dynamic-import 导入的组件使用v-if 显示,以便在需要时加载它们。当它们被显示时,它们的 JavaScript 也会被加载。但在slot 的情况下,v-if 不会阻止组件已经加载其生成的 JavaScript 块并将其附加到 DOM。

下拉组件:

<template>
    <li class="dropdown" :class=" open: visible ">
        <div class="heading" @click.stop="toggle">
            <span> heading </span>
        </div>

        <div class="slot-content" v-if="visible">
            <slot></slot>
        </div>
    </li>
</template>

在槽中使用带有异步google-map组件的组件:

<dropdown>
    <google-map>
        <map-marker :data=" $marker "></map-marker>
    </google-map>
</dropdown>

即使插槽有v-if,JavaScript 组件仍在加载中。奇怪的是,mounted 或 created 都没有被触发。因此,除了组件的异步加载之外,似乎一切都遵守适当的规则。

最好我可以将插槽与v-if 一起使用,而不是触发为该async 组件加载生成的块。

如果异步加载显然不是什么大问题,但即使是 HTTP2 在涉及请求时也有其限制。我宁愿在需要时加载它。

【问题讨论】:

尝试使用v-cloak,它将用CSS隐藏html,直到组件完全加载。 v-cloak 只是应用一个dislay: none,它不会阻止异步生成的 JavaScript 仍然被加载。另外,我已经尝试过使用它,但无济于事。 【参考方案1】:

来自the doc about Compilation Scope

父模板中的所有内容都在父范围内编译; 子模板中的所有内容都在子范围内编译。

这就是您出现问题的原因。父模板中没有任何内容表明不应渲染组件。

可以通过Scoped Slots

来解决

简单示例:https://jsfiddle.net/jacobgoh101/8kmLpj75/6/

在示例中,只需将&lt;template slot-scope=""&gt; 添加到异步组件,它就会强制异步组件等待,直到插槽的父范围可用。 (老实说,我也不知道它的确切内部工作原理)。

在您的情况下,只需添加 &lt;template slot-scope=""&gt; 也应该可以解决问题

<dropdown>
    <template slot-scope="">
        <google-map>
            <map-marker :data=" $marker "></map-marker>
        </google-map>
    </template>
</dropdown>

【讨论】:

谢谢,这似乎有效,但我希望对它的工作原理进行更多解释。但它现在完成了这项工作。谢谢! 我也很惊讶这行得通,也很想解释一下哈哈

以上是关于Vue 插槽在插槽 v-if 语句启动之前加载异步组件的主要内容,如果未能解决你的问题,请参考以下文章

Vue-七七创建全局组件——“Loading“ 使用extend创建组件——弹出层 单继承:vue组件间的继承。——继承js的部分 异步组件加载 异步组件工厂 组件插槽

vue 插槽的使用

56-61 组件插槽动态组件,异步组件

vue 作用域插槽(插槽赋值)

Vue 作用域插槽

vue 2.6 插槽更新 v-slot 用法总结