确定槽内容是空还是空

Posted

技术标签:

【中文标题】确定槽内容是空还是空【英文标题】:Determining if slot content is null or empty 【发布时间】:2018-05-06 01:46:28 【问题描述】:

我有一个小加载组件,我希望其默认文本为“加载中...”。插槽的好候选人,所以我有这样的东西作为我的模板:

<p class="loading"><i class="fa fa-spinner fa-spin"></i><slot>Loading...</slot></p>

这使我可以更改加载消息,例如<loading>Searching...</loading>。不过,我想要的行为不仅是在未提供插槽内容时显示默认消息,而且在插槽内容为空或空白时显示默认消息。目前,如果我执行例如<loading>loadingMessage</loading> 并且 loadingMessage 为空,则不会显示任何文本(我希望显示默认文本)。所以理想情况下我需要测试this.$slots.default。这告诉我内容是否传入,但我如何找到它是否为空? this.$slots.default.text 返回未定义。

【问题讨论】:

【参考方案1】:

您需要一个计算属性来检查this.$slots。对于默认插槽,您需要检查 this.$slots.default,对于命名插槽,只需将 default 替换为插槽名称即可。

computed: 
  slotPassed() 
    return !!this.$slots.default[0].text.length
  

然后在你的模板中使用它:

<template>
  <div>
    <slot v-if="slotPassed">Loading...</slot>
    <p v-else>Searching...</p>
  </div>
</template>

你可以看一个小例子here。请注意后备内容的显示方式,而不是插槽内的“默认内容”。


编辑: 我的措辞本来可以更好。您需要做的是检查$slots.X 值,但计算属性是一种方法来检查。您也可以在模板中编写插槽检查:

<template>
  <div>
    <slot v-if="!!$slots.default[0].text">Loading...</slot>
    <p v-else>Searching...</p>
  </div>
</template>

编辑 2:正如 @GoogleMac 在 cmets 中指出的那样,对于无渲染组件(例如 &lt;transition&gt;&lt;keep-alive&gt;、...),检查插槽的文本属性失败,因此检查他们建议的是:

!!this.$slots.default && !!this.$slots.default[0]

// or..
!!(this.$slots.default || [])[0]

【讨论】:

我看到的问题是$slots.default.text 始终未定义。这是一个 jsfiddle:jsfiddle.net/JohnMoore/rmafyz2x/2 我的错,$slots.default 是一个数组,所以你需要的是$slots.default[0].text :) 是的,这就是我一直在寻找的答案。只要我能测试$slots.default[0].text,我就能实现我想要的。 对我来说,有一个插槽通过,但上面的答案仍然失败,因为插槽是一个 Vue &lt;transition&gt; 元素,里面有另一个元素。过渡元素的文本属性为undefined。就我而言,我有一个计算属性,它返回 !!this.$slots.default &amp;&amp; !!this.$slots.default[0] @GoogleMac 啊哈,对我来说是 TIL 时刻!感谢分享,我已经编辑了我的答案以包含您的见解【参考方案2】:

@kano 的回答效果很好,但有个问题:this.$slots 不是反应式的,所以如果它开始是false,然后变成true,任何computed 属性都不会更新。

解决方案是不依赖computed 值,而是依赖createdbeforeUpdated (as @MathewSonke points out):

export default 
  name: "YourComponentWithDynamicSlot",
  data() 
    return 
      showFooter: false,
      showHeader: false,
    ;
  ,
  created() 
    this.setShowSlots();
  ,
  beforeUpdate() 
    this.setShowSlots();
  ,
  methods: 
    setShowSlots() 
      this.showFooter = this.$slots.footer?.[0];
      this.showHeader = this.$slots.header?.[0];
    ,
  ,
;

更新:Vue 3(组合 API)

对于 Vue 3,检查插槽是否有内容的方式似乎发生了变化(使用新的组合 API):

import  computed, defineComponent  from "vue";

export default defineComponent(
  setup(_,  slots ) 
    const showHeader = computed(() => !!slots.header);

    return 
      showHeader,
    ;
  ,
);

注意:我找不到任何关于此的文档,所以请稍加注意,但似乎在我非常有限的测试中有效。

【讨论】:

对于 Vue 2,如果您使用的是作用域插槽,那么引用实际上是一个函数,而不是一个对象。所以你必须在检查子元素之前执行它。 const scopedSlot = this.$scopedSlots.myScopedSlot; const scopedSlotResolved = scopedSlot(); const hasChild = !!(scopedSlotResolved?.[0]); 然后可以进行空检查,因为作用域槽引用直到生命周期的后期才会成为函数。

以上是关于确定槽内容是空还是空的主要内容,如果未能解决你的问题,请参考以下文章

如何刮内容?

如何检查datareader是空还是空

检查字符串是空还是空的最简单方法

sql 中判断一个字段的值是空还是有值

Spring Data Pageable:返回空内容

用C语言怎么判断一个int变量是空还是为0