Skip to content

关于插槽判断的兼容性问题与思考 #45

@jiangmaniu

Description

@jiangmaniu

问题描述

在 uniapp 的 v3.x 的文档中,注明 APP 端不支持 $slots

image

意味着整个UI库的 $slots.xxx 的判断都无法生效,就会导致在 APP 端,使用自定义插槽时,组件内无法判断。

例如在 u-cell 组件中使用自定义插槽 right-icon 时,组件由于拿不到 $slots 的值,无法通过 v-if 判断显示

<view class="u-cell__right-icon-wrap" v-if="$slots['right-icon'] || isLink"

以上只是其中一个例子,整个库中有多个地方都有使用到 $slots.xxx,可能都会有该问题

解决思路

我在自己写组件的时候也有遇到这个问题,我目前想到两种方案

1. 添加 props 属性来注明是否使用自定义插槽

继续上个例子举例,在 props 中添加 customRightIcon 属性,在模板中替换掉 $slots.xxx 的判断

props: {
    customRightIcon: { type: Boolean, default: false } 
}
<view class="u-cell__right-icon-wrap" v-if="customRightIcon || isLink">
...
</view>

该方案的好处在于:已知的兼容性好,全平台都可兼容
该方案的坏处在于:每个需要 v-if 判断的自定义的插槽都需要定义 props,使用者每次都需要写上自定义插槽的同时,添加对应的判断 props 属性,增加使用者的心智负担,并且会使不需要兼容 APP 的开发者也需要添加自定义属性。

针对不需要兼容 APP 的方案

props 定义的判断属性,不在替换代替 $slot.xxx,而是在原有 v-if 的判断条件上添加 props 属性

<view class="u-cell__right-icon-wrap" v-if="$slots['right-icon'] || isLink || customRightIcon ">
...
</view>

需要兼容 APP 的开发者,在写插槽的同时添加上插槽对应的自定义 props 属性,否则直接写上插槽即可

2. 通过 vm.$scopedSlots 判断是否使用

根据上面 v3.x 的介绍可得,v3.x 是兼容 $scopedSlots,并且在 APP 中粗略测试后,发现在不指定 slot-scope 的情况下也能获取到传入的插槽

<!-- 业务 -->
<u-cell>
  <view>这是 default 插槽</view>
  <template #right-icon>
    <view>这是 right-icon 插槽</view>
  </template>
</u-cell>

<!-- u-cell -->
mounted() {
 console.log(this.$scopedSlots)
}

image

由此可在原有 v-if 判断条件基础添加 $scopedSlots.xxxx 条件,即可兼容 APP 端

该方案的问题在于:只是简单的看了一下 $scopedSlots api 拥有传入 slot,没有完整测试跨平台的兼容性。

最后

以上思路的可行性如被通过,我很乐意为此方案提交 PR!如果有更好的实现思路,欢迎留言一起探讨学习。

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions