微信小程序tab切换—swiper组件中使用slot的问题(已放弃slot方式,采用tab组件和swiper组件相互传值)

题目描述

微信小程序的swiper组件中的swiper-item标签里使用了slot,但是现在slot的内容不显示,不知道什么原因,也有百度到swiper中不让嵌套其他,但是这个其他包不包括slot我也不清楚,文档上我也没有找到相关的描述

题目来源及自己的思路

做一个tab切换的功能,content部分用swiper组件来实现,单个页面已经可以实现。现在我想把这部分抽离出来做成一个可复用的组件,那就意味着内容是动态的,我的想法是用slot来实现,但是最后的效果一直都不对

相关代码

调用组件的页面:

<tab menu='{{menu}}'>
    <view class='borrow-list' id='list'>
        我是slot
    </view>
</tab>

tab组件的代码:

<view class='tabMenu'>
    <view class='tabItem' bindtap='tabChange'>
        <view wx:for='{{menu}}' wx:key='{{index}}' id='t{{index+1}}' data-flag='{{index}}' class='{{active==("t"+(index+1)) ? "active":""}}'>{{item.text}}</view>
    </view>
    <view id='tabline' class='tabline' style='left:{{left||"91rpx"}}'></view>
</view>
<view>
    <swiper bindchange='swiperChange' current = '{{current}}' style='height:{{swiperHeight+"px"}}'>
        <swiper-item item-id='t1'>
            <slot></slot>
        </swiper-item>
    </swiper>
</view>  

这样写之后在console查看代码结构如下:
图片描述

slot的内容没有插入到swiper-item中,然后我又给slot加了name,最后的结果如下:
图片描述

问题一:swiper中slot能不能使用(文档中哪里有体现)
问题二:swiper中如果不能使用slot,那有什么办法可以实现动态内容部分
其实我之前还尝试了另一个办法,就是swiper不写在tab组件内写在调用tab的页面里,但是因为有联动效果(滑动内容,tab菜单动态切换;点击tab菜单,内容滑动变化)导致传值是个问题,因为小程序没有监听data变化的函数(比如watch),所以一旦我滑动内容部分,传给tab组件的值的变化我是监听不到的。如果根据这个思路,大家有解决的办法,也可以留言~3Q~

阅读 6.6k
3 个回答

已解决,解决方案如下:
我最后采用了我的问题末尾提到的思路,tab的多个标签是一个组件,swiper放在调用组件的page页中,那就面临着要解决page和组件的传值问题,看了一篇写vue中watch的实现思路的文章(地址:https://segmentfault.com/a/11...)有所启发,使用Object.defineProperty()给监听的属性设置存取器属性,存取器属性包含set和get方法,当属性发生变化时,set和get自动触发达到监听属性变化的目的

代码实现部分:
组件调用方式:(menu是tab的选项名称以及id等信息,是一个数组;currentItemId是当前swiperItem的item-id)

<tab menu='{{menu}}' currentItemId='{{currentItemId}}' bind:changeEvent='changeEvent'></tab>

page页中swiper组件:(swiperChange中能获取到currentItemId)

<swiper bindchange='swiperChange' current = '{{current}}' style='height:{{swiperHeight+"px"}}'>
    <swiper-item item-id='t1'>
    //内容
    </swiper-item>
    <swiper-item item-id='t2'>
    //内容
    </swiper-item>
</swiper>

tab组件中接收currentItemId:

/**
   * 组件的属性列表
   */
  properties: {
    menu: {
       type: Array,
       value: null
    },
    currentItemId: {
       type: String
    }
  }

同时在tab组件中定义一个初始数据方便之后使用Object.defineProperty():

/**
   * 组件的初始数据
   */
  data: {
    copy: {}
  },

之后在组件js的methods中定义watch函数,监听的是接收到的currentItemId

watch: function (val) { 
      let _this = this
      Object.defineProperty(_this.data, 'currentItemId', { //需要监听的currentItemId
        enumerable: true,
        configurable: true,
        get: function () {
          return _this.data.copy.currentItemId //此处使用的copy,其中的currentItemId字段始终与this.data.currentItemId相等,不可使用this.data.currentItemId,会造成死循环
        },
        set: function (newVal) {
          var value = _this.data.copy.currentItemId
          if (newVal === value) {
            return
          }
          //为了使this.data.currentItemId == this.data.copy.currentItemId,需要在每一次this.data.currentItemId变化的时候也就是执行set的时候为this.data.copy赋值 使两个字段的值始终保持一致
          _this.setData({
            copy: {
              currentItemId: newVal
            }
          })
          //这个方法计算应该切换到哪个选项的,不是问题的重点就不贴代码了
          _this.currCompute(_this.data.copy.currentItemId)
        }
      })
      _this.setData({
          copy: {
            currentItemId: _this.data.currentItemId
          }
      })
    }

-----------------以上完成了从page页传值到tab组件,tab组件中监听swiper的变化------------------
接下来说一下tab组件传值到page页,就是组件中绑定的那个自定义事件changeEvent了,再贴一次代码:

 <tab menu='{{menu}}' currentItemId='{{currentItemId}}' bind:changeEvent='changeEvent'></tab>

当tab组件中的选项被点击切换的时候触发changeEvent自定义事件,同时page页定义changeEvent函数来接收传过来的值(注意自定义事件名称和触发函数的名称没关系,就是懒得再起一个名称而已)
tab组件js中的操作:

/*tab切换事件 */
    tabChange: function (e) {
      let id = e.target.id
      var data = {
        current: e.target.dataset.flag
      } 
      this.triggerEvent('changeEvent', data) //changeEvent自定义事件的名称
    },

page页中接收:
changeEvent: function(data) {

this.setData({
  current: data.detail.current
})

}
-----------------以上完成了从tab组件传值到page页的操作,如果熟悉vue中的子组件向父组件传值,应该可以理解的------------------

以上,多谢@师宁丶童鞋和@WsmDyj童鞋解答~

建议自己封装一个swiper组件,或者引用iview中的swiper

你好 老铁 谢邀,这个问题我们公司在写公用组件库的遇到过这个问题关于wepy动态插槽无法生成的问题,也提给官方了,坐等解决,如果你使用的是wepy这个框架时,使用slot记得对应的name,如果动态的要生成多个的swiperitme并且有插槽位置的话,每一个slot的name记得命为不同的,原生小程序是没有slot这个插槽的,如果想使用slot的话 推荐使用wepy或者mpvue。

推荐问题
宣传栏