# 前言
要在 uni-app 中使用动态 slot 名字,会比较麻烦,因为:在 MP-WEIXIN、APP-PLUS 都会有坑。
# H5 和 小程序端
我们先说比较常用的 H5 和 MP-WEIXIN 好了:
定义:
<!-- HACK: uni-app 处理动态 slot 名字不兼容,需要使用不同的语法 --> <!-- #ifdef H5 --> <slot :name="`tab:${item.key}`"></slot> <!-- #endif --> <!-- #ifdef MP-WEIXIN--> <slot name="tab:{ {item.key}}"></slot> <!-- #endif -->
使用 slot:
<view> <!-- HACK: uni-app 处理动态 slot 名字不兼容,需要使用不同的语法 --> <!-- #ifdef H5 --> <template v-for="item in list" :slot="`tab:${item.id}`"> <post-list :key="item.id" /> </template> <!-- #endif --> <!-- #ifdef MP-WEIXIN--> <template v-for="item in lits" slot="tab:professional:{ {item.id}}"> <post-list :key="item.id" /> </template> <!-- #endif --> </view>
# APP 端
如果还要兼容 APP 端(vue 文件),则情况会变得稍微复杂一点,以上两种情况都不适用,先说结论:
- 不支持拿 data 的数据用于拼接动态 slot 名字
- 在 v-for 中要根据当前项的字段来拼接 slot 名字,则要将 key 指向item 本身(不推荐
- 能拿 v-for 的 index 来拼接 slot 名字(推荐
# 解决方案
也即,如果是上面的例子,需要改写为如下::
<swiper-item v-for="(item, index) in tabs" :key="item.id" class="swiper-item"> <!-- HACK: uni-app 处理动态 slot 名字不兼容,需要使用不同的语法 --> <!-- #ifdef H5 || APP-PLUS --> <slot :name="`tab:${index}`"></slot> <!-- #endif --> <!-- #ifdef MP-WEIXIN--> <slot name="tab:{ {index}}"></slot> <!-- #endif --> </swiper-item>
使用的时候:
<tab-swiper ref="tabSwiper" :tabs="list" :current.sync="current" :swiper-current.sync="swiperCurrent" > <!-- HACK: uni-app 处理动态 slot 名字不兼容,需要使用不同的语法 --> <!-- #ifndef H5 || APP-PLUS --> <template v-for="(item, index) in list" :slot="`tab:${index}`"> <post-list :key="item.id" :stagger="index % 2 !== 0" /> </template> <!-- #endif --> <!-- #ifdef MP-WEIXIN--> <template v-for="(item, index) in list" slot="tab:{ {item.id}}"> <post-list :key="item.id" :stagger="index % 2 !== 0" /> </template> <!-- #endif --> </tab-swiper>
# 排查问题
下面开始排查问题,首先我们用以下代码测试用 data 的数据来作为 slot 名字:
<template> <view> testing dynamic slot <slot :name="key"></slot> <view :class="key"> test key value </view> </view> </template> <script> export default { data() { return { key: 'slot-1', } }, } </script>
可以看到,即便同样使用了 key 作为属性,但它们编译后的代码是不一样的,slot 节点直接使用_vm._key,而 view 节点变成了_vm._$(2,'c'),由此也推断出 uni-app 内部并没有对 slot 的name属性做额外处理,其实如果打印_vm.key的值, 会发现是空的:
所以结论一:不支持拿 data 的数据用于拼接动态 slot 名字。
但直接拿 data 数据来拼接 slot 名字的情况比较少,更多时候是在 v-for 循环内部,所以我们再拿以下代码做测试:
<template> <view> testing dynamic slot <view v-for="item in list" :key="item.id"> { { item.name }} <slot :name="`tab:${item.id}`"></slot> </view> </view> </template> <script> export default { data() { return { list: [ { id: 'a', name: 'item-a', }, { id: 'b', name: 'item-b', }, { id: 'c', name: 'item-c', }, ], } }, } </script>
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。