umicro / uView2.0

uView UI,是全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
MIT License
1.54k stars 462 forks source link

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

Open jiangmaniu opened 2 years ago

jiangmaniu commented 2 years ago

问题描述

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

image

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

例如在 u-cell 组件中使用自定义插槽 right-icon 时,组件由于拿不到 $slots 的值,无法通过 v-if 判断显示 https://github.com/umicro/uView2.0/blob/5fd2933dd788a58c21b12aa91590de66e299821c/uni_modules/uview-ui/components/u-cell/u-cell.vue#L28

以上只是其中一个例子,整个库中有多个地方都有使用到 $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!如果有更好的实现思路,欢迎留言一起探讨学习。

BeiQiaoT commented 2 years ago

感谢建议,我们内部会探讨一下

Jason-mimo commented 2 years ago

关于第二种方法,我在iPhone 6 Plus 和 Redni K40 Gaming 两款机型上测试:把原有的 vm.$slots 方法去除, 添加 vm.$scopedSlots 方法,在app都可以很好的实现具名插槽的判断。在不影响原有的组件使用和条件判断可以使用Uniapp的条件编译来兼容app