8***@qq.com
8***@qq.com
  • 发布:2020-06-11 10:24
  • 更新:2021-06-02 16:06
  • 阅读:7685

【报Bug】小程序端自定义组件的带参数插槽(slot-scope),数据传递有问题,并且事件绑定无法生效

分类:uni-app

产品分类: uniapp/小程序/微信

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: win10 1903

HBuilderX类型: 正式

HBuilderX版本号: 2.7.9

第三方开发者工具版本号: 1.03.2005140

基础库版本号: 2.9.2

项目创建方式: HBuilderX

示例代码:

组件1的代码,带有slot-scope特性
@/components/slot-test/slot-test.vue

<template>  
  <view>  
    <slot></slot>  
    <slot name="test"></slot>  
    <view v-for="(item, index) in list" :key="index">  
      <slot name="item" :item="item" :index="index"></slot>  
    </view>  
  </view>  
</template>  
  
<script>  
    
export default {  
  name: 'slot-test',  
  props: {  
    list: {  
      type: Array,  
      default () {  
        return []  
      }  
    }  
  }  
}  
    
</script>  
  
<style>  
</style>

组件2的代码,纯粹只是一个容器
@/components/slot-test/another-slot.vue

<template>  
  <view>  
    <slot></slot>  
  </view>  
</template>  
  
<script>  
</script>  
  
<style>  
</style>

测试页面的代码

<template>  
  <view>  
    <view style="margin: 20px;">下面是暴露在外部的自定义组件</view>  
    <slot-test v-if="asyncList" :list="syncList">  
      <view style="background-color: red; margin: 20px;" @click="defaultClickHandler">点我检查默认插槽的点击事件</view>  
      <template v-slot:test>  
        <view style="background-color: green; margin: 20px;" @click="nameClickHandler">点我检查具名插槽的点击事件,下面是带有slot-scope的具名插槽,点击可以检查事件</view>  
      </template>  
      <template v-slot:item="{ item, index }">  
        <view style="background-color: yellow; margin: 20px;" @click="clickHandler(item, index)">  
          <view>slot-scope传来数据 {{ item.txt }}</view>  
          <view>slot-scope传来索引 {{ index }}</view>  
          <view>同步数据 {{ syncList[index].txt }}</view>  
          <view>异步数据 {{ asyncList[index].txt }}</view>  
        </view>  
      </template>  
    </slot-test>  
      
    <view style="margin: 20px;">下面是嵌套在自定义组件内部的自定义组件</view>  
    <another-slot>  
      <slot-test v-if="asyncList" :list="syncList">  
        <view style="background-color: red; margin: 20px;" @click="defaultClickHandler">点我检查默认插槽的点击事件</view>  
        <template v-slot:test>  
          <view style="background-color: green; margin: 20px;" @click="nameClickHandler">点我检查具名插槽的点击事件,下面是带有slot-scope的具名插槽,点击可以检查事件</view>  
        </template>  
        <template v-slot:item="{ item, index }">  
          <view style="background-color: yellow; margin: 20px;" @click="clickHandler(item, index)">  
            <view>slot-scope传来数据 {{ item.txt }}</view>  
            <view>slot-scope传来索引 {{ index }}</view>  
            <view>同步数据 {{ syncList[index].txt }}</view>  
            <view>异步数据 {{ asyncList[index].txt }}</view>  
          </view>  
        </template>  
      </slot-test>      
    </another-slot>  
  
  </view>  
</template>  
  
<script>  
import slotTest from '@/components/slot-test/slot-test.vue'  
import anotherSlot from '@/components/slot-test/another-slot.vue'  
  
export default {  
  name: 'slotBug',  
  components: {  
    slotTest,  
    anotherSlot  
  },  
  data () {  
    return {  
      syncList: [  
        { txt: '1' },  
        { txt: '2' },  
        { txt: '3' }  
      ],  
      asyncList: null  
    }  
  },  
  methods: {  
    clickHandler (item, index) {  
      console.log('来自默认插槽传来的数据', item.txt)  
      console.log('插槽的索引值', index)  
      console.log('索引值调用同步数据', this.syncList[index].txt)  
      console.log('索引值调用异步数据', this.asyncList[index].txt)  
    },  
      
    defaultClickHandler () {  
      console.log('默认插槽')  
    },  
    nameClickHandler () {  
      console.log('具名插槽')  
    }  
  },  
  created () {  
    setTimeout(() => {  
      this.asyncList = [  
        { txt: '11111111' },  
        { txt: '22222222' },  
        { txt: '33333333' }  
      ]  
    }, 3000)  
  }  
}  
</script>  
  
<style>  
</style>

操作步骤:

附件我上传了每次复现uni-app的各种坑的应用,这次的问题在/pages/slotBug/slotBug页面
不想下载附件,代码实例中也包含了复现代码。

预期结果:

我希望小程序端能和H5端的表现一致

实际结果:

小程序端的slot-scope表现异常

bug描述:

首先,我在 https://ask.dcloud.net.cn/question/95109 这个问题中反应了uni-app的APP端不支持 <slot :name="xxx"></slot> 的写法,但是在后续的版本更新中我没有看到此方面的优化。

于是我通过slot-scope传递参数来绕过这个问题,但是slot-scope在微信小程序端有坑,我总结下来有两点。

  1. 子组件的slot-scope中,如果传递v-for带来的index索引,则无法通过这个index获取到父组件data中的数组数据。例如
<comp>  
  <template v-slot:xxx="{ index }">  
    {{ list[index] }}  
  </template>  
</comp>

以上模板,slot-scope中的list[index]全部都是undefined

  1. 如果带有slot-scope的子组件嵌套在另一个自定义组件中,那么slot中绑定的自定义事件甚至会失效
<comp1>  
  <comp2>  
    <template v-slot:xxx="{ index }">  
      <view @click="clickHandler">{{ index }}</view>  
    </template>  
  </comp2>  
</comp1>

点击这个clickHandler一定会报错 thirdScriptError
_vm.clickHandler is not a function; [Component] Event Handler Error

我在复现应用中已经复现了这些问题

2020-06-11 10:24 负责人:DCloud_UNI_GSQ 分享
已邀请:
8***@qq.com

8***@qq.com (作者)

slot-scope在小程序端看起来是独立分离成子自定义组件实现的,但是存在数据失效,样式失效,某些场景下事件回调也会失效。
这么说来,这个问题其实不算BUG,是小程序方面不支持slot-scope这种特性,uni-app框架提供的解决方案存在缺陷。
希望框架能早日做到三端语法统一吧,我感觉现在写惯了原生Vue的用uni-app真的是一脚一个坑。

DCloud_UNI_GSQ

DCloud_UNI_GSQ

HBuilderX 2.8.1 作用域插槽的事件和样式已修复

作用域插槽内不能访问作用域外数据的限制参考:https://github.com/dcloudio/uni-app/issues/495

极星123

极星123

目前也是遇到此类头疼的问题,微信小程序各种undefined,好头疼

梦尋Junjie

梦尋Junjie - 原来她有男朋友

我现在也是怂的 ,

微信小程序 还不能支持 slot-scope , 我 的解决办法是 吧要用的传递给 组件,然后再在组件里传递出来

//-> 父级页面

//-> 组件

laravuel

laravuel

APP端作用域插槽,还有一个BUG。

首先这个插槽是一个列表
如果在插槽内部写上两个自定义组件,并且用v-if v-else,那么第二次遍历后组件数据将失效。

<template v-slot="{ item }">  
    <component-first v-if="xxx"></component-first>  
    <component-second v-else></component-second>  
</template>

component-second组件会失效,必须写成下面这种形式才可以:

<template v-slot="{ item }">  
    <component-first v-if="xxx"></component-first>  
    <component-second v-if="!xxx"></component-second>  
</template>
DCloud_UNI_GSQ

DCloud_UNI_GSQ

bug 确认,已加分,后续优化

  • 落叶疏影

    请问插槽的作用域问题是否在解决中,我是将H5转为uniapp的,很多地方都用到了这个功能。


    2020-10-20 21:11

  • DCloud_UNI_GSQ

    回复 落叶疏影: 作用域插槽内不能访问作用域外数据的限制吗?这个近期还没合适的处理方案,你将要使用到的数据传入组件内


    2020-10-22 11:23

  • laravuel

    这个问题,最近有解决吗


    2021-02-25 10:51

  • laravuel

    回复 DCloud_UNI_GSQ: 关键是方法都没法用,难道方法也要传递进去吗


    2021-02-25 10:56

  • 梦尋Junjie

    回复 laravuel: 这个简单 ,


    2021-03-11 18:55

  • DCloud_UNI_GSQ

    作用域插槽内不能访问作用域外数据的限制参考:https://github.com/dcloudio/uni-app/issues/495


    2021-06-02 16:06

该问题目前已经被锁定, 无法添加新回复