Vue.js 仅显示包含内容的插槽

Vue.js 仅显示包含内容的插槽,vue.js,vuejs2,Vue.js,Vuejs2,是否有一种方法仅在插槽有任何内容时显示它 例如,我正在构建一个简单的Card.vue组件,我只希望在页脚插槽包含以下内容时显示页脚: 模板: <template> <div class="panel" :class="panelType"> <div class="panel-heading"> <h3 class="panel-title"> <slot nam

是否有一种方法仅在插槽有任何内容时显示它

例如,我正在构建一个简单的
Card.vue
组件,我只希望在页脚插槽包含以下内容时显示页脚:

模板:

<template>
    <div class="panel" :class="panelType">
        <div class="panel-heading">
            <h3 class="panel-title">
                <slot name="title">
                    Default Title
                </slot>
            </h3>
        </div>

        <div class="panel-body">
            <slot name="body"></slot>

            <p class="category">
                <slot name="category"></slot>
            </p>
        </div>

        <div class="panel-footer" v-if="hasFooterSlot">
            <slot name="footer"></slot>
        </div>
    </div>
</template>

默认标题

脚本:

<script>
    export default {
        props: {
            active: true,
            type: {
                type: String,
                default: 'default',
            },
        },

        computed: {
            panelType() {
                return `panel-${this.type}`;
            },

            hasFooterSlot() {
                return this.$slots['footer']
            }
        }
    }
</script>

导出默认值{
道具:{
主动:对,
类型:{
类型:字符串,
默认值:“默认值”,
},
},
计算:{
panelType(){
返回`panel-${this.type}`;
},
hasFooterSlot(){
返回此。$slots['footer']
}
}
}
鉴于:

<card type="success"></card>

因为上面的组件不包含页脚,所以不应该呈现它,但它是

我尝试使用
this.$slots['footer']
,但它返回未定义的值


有人有什么建议吗?

应该在

this.$slots.footer
所以,这应该行得通

hasFooterSlot() {
  return !!this.$slots.footer
}

.

您应该检查
vm.$slots
以及
vm.$scopedSlots

hasSlot (name = 'default') {
   return !!this.$slots[ name ] || !!this.$scopedSlots[ name ];
}

我也遇到过类似的问题,但在广泛的代码库中,当创建原子设计结构化组件时,总是要编写
hasSlot()
方法,而当涉及到TDD时,这又是一个需要测试的方法。。。尽管如此,您始终可以将原始逻辑放在
v-if
中,但我发现模板最终会变得杂乱无章,有时更难阅读,特别是对于检查代码结构的新开发人员

我的任务是找到一种方法,在插槽未提供时删除插槽的父
div
s

问题:


//实例化
向我展示
//呈现
向我展示

希望我能正确理解这一点。如果插槽为空,为什么不使用未呈现的
标记呢

<slot name="foo"></slot>

像这样使用它:

<template slot="foo">
   ...
</template>

...

简而言之,在内联中执行此操作:

<template lang="pug">
  div
    h2(v-if="$slots.title")
      slot(name="title")
    h3(v-if="$slots['sub-title']")
      slot(name="sub-title")
</template>

div
h2(v-if=“$slots.title”)
插槽(name=“title”)
h3(v-if=“$slots['sub-title']”)
插槽(名称=“子标题”)
起初我认为它是有效的,但我不得不对它进行一些扩展,因为$scopeSlots返回一个函数,无论其返回值如何,该函数总是真实的。这是我的解决方案,尽管我已经得出结论,这个问题的真正答案是“这样做是一种反模式,如果可能的话,你应该避免这样做”。例如,只需制作一个单独的页脚组件,可以插入其中

黑胶溶液 最佳实践(页脚的帮助器组件)
const panelComponent={
模板:`
`
}
常量页脚组件={
模板:`
`
}
var app=新的Vue({
el:“#应用程序”,
组成部分:{
面板组件,
页脚组件
},
数据(){
返回{
名称:“Vue”
}
}
})
。漂亮的面板{
最大宽度:200px;
边框:1px实心浅灰色;
}
.漂亮的面板内容{
填充:30px;
}
.漂亮的面板页脚{
背景颜色:浅灰色;
填充:5px30px;
文本对齐:居中;
}

带页脚的面板
乱数假文
一些页脚内容
无页脚面板
乱数假文

CSS大大简化了这一点。只要使用下面的代码,瞧

.panel-footer:empty {
  display: none;
}

这是Vue 3合成API的解决方案:


从“vue”导入{ref};
导出默认值{
设置(道具,{slots}){
const Hastintle=ref(假)
//按名称检查插槽是否存在,是否有内容。
//如果为空,则返回一个空数组。
if(slots.title&&slots.title().length){
hasttle.value=true
}
返回{
黑斯特尔
}
}
}

有效!抱歉,这是我的错,在将内容输入插槽时使用了错误的语法。谢谢!!:)
this.$slots.footer
this.$slots['footer']
是等价的,不是吗?这真的是解决方案还是出了什么问题?@DanielBeck你是对的,他们都指向同一件事。如果没有内容,两者都将返回undefined。唯一不同的是我返回一个布尔值,但是,测试它时,从hasFooterSlot返回undefined将导致v-if隐藏组件。。因此,从技术上讲,我认为您的代码应该是有效的。(澄清一下,我不是最初的询问者,只是一个感兴趣的观察者:)这似乎在Vue 2.6中的所有情况下都不起作用-当其他$ScopeDSlot存在时,错误地返回false(至少在某些情况下,例如从dom中删除并通过
v-if
添加回来的元素)但是
这是。$scopedSlots[name]
返回一个渲染函数,而不是像
vm那样的vNode数组。$slots
执行。因此,最后它强制为布尔值true。我的
this。$slots
是一个空对象,
this。$scopedSlots
帮助我。有关考虑到
$scopeSlots[name]
是一个函数(Vue 2.1.0+)的答案,请参阅太棒了!谢谢!问题是当您希望外部元素包装插槽时,但不希望在插槽未给定或为空时渲染外部元素。这无法解决用例问题。这很酷,但由于各种边缘情况、scopedSlots、默认插槽内部内容(名为slot)而存在下滑s、 等等;依我的拙见,包装槽似乎是一种反模式,也许最好问问我
.panel-footer:empty {
  display: none;
}