微信小程序组件: tab标签页

需求:

  1. 插槽为动态, 可以在使用页面自行设置
  2. 可以自定义设置每个tab的样式, 也可以设置容器的样式
  3. 如果tab太多, 容器可以横向滚动
  4. 设置当前tab值可以自动定位到当前tab位置

思路:

  1. slot属性name动态设置
  2. 设置默认样式, 写好公共的方法, 将对象转换成style可以用的字符串
  3. scroll-x
  4. scroll-into-view

效果图:

组件代码 ⬇️
wxml

<view class="tabs-container">
  <scroll-view style="{{tabsConStyle}}" class="pane-con" scroll-x enhanced bounces scroll-into-view="{{currentTab}}">
    <view wx:for="{{tabs}}" wx:key="id" id="{{item.id}}" class="tabs-pane inline {{index === activeTab ? 'active' : ''}}" style="{{index === activeTab ? paneActiveStyle : paneStyle}}" bindtap="switchTab" data-index="{{index}}">{{item.label}}</view>
  </scroll-view>
  <block wx:for="{{tabs}}" wx:key="id">
    <!-- 可以使用每项对应的插槽 -->
    <view class="tabs-content" wx:if="{{activeTab === index}}">
      <slot name="{{index}}"></slot>
    </view>
    <!-- 如果使用页面中每tab只是数据不同或其它情况, 也可以使用这个默认插槽 -->
    <slot></slot>
  </block>
</view>

js

Component({
  options: {
    multipleSlots: true
  },
  properties: {
    // 必传参: tabs数组, 每项需要传一个包含属性名为label和属性名为id唯一值的对象
    tabs: {
      required: true,
      type: Array,
      value: () => {
        return [{
          label: "",
          id: ""
        }]
      }
    },
    // 非必传: 当前tab初始值
    activeTab: {
      type: Number,
      value: 0
    },
    // 非必传: 每一项的样式
    tabStyle: Object,
    // 非必传: 当前项的样式
    tabActiveStyle: Object,
    // 非必传: 可滑动tabs容器的样式
    tabsStyle: Object,
  },
  data: {
    paneStyle: "",
    paneActiveStyle: "",
    tabsConStyle: "",
    flag: false,
    // 为固定tabCon左滑的位置
    currentTab: "",
  },
  methods: {
    initTabs() {
      // 共三个参数的赋值过程
      // 思路: 
      // 1. 都需要经过对象转字符串过程
      // 2. 如果有普通每项, 则先将当前项的特殊样式与普通项样式合并, 再进行字符串处理
      this.setData({
        paneStyle: this.transferObjToStr(this.data.tabStyle),
        paneActiveStyle: this.data.tabStyle ? this.transferObjToStr(Object.assign(this.data.tabStyle, this.data.tabActiveStyle)) : this.transferObjToStr(this.data.tabActiveStyle),
        tabsConStyle: this.transferObjToStr(this.data.tabsStyle),
      })
    },
    switchTab(event) {
      // 切换方法: 设置当前项, 并传值
      this.setData({
        activeTab: event.currentTarget.dataset.index,
      })
      this.triggerEvent('switchTab', this.data.activeTab);
    },
    transferObjToStr(obj) {
      // 小程序中style不可以像VUE一样直接使用对象, 而传入的是对象, 这一步是将传入的style对象转换成组件中可以直接使用的字符串
      if (!obj) return "";

      let str = "";
      for (let key in obj) {
        str += `${key}: ${obj[key]};`;
      }
      return str;
    },
  },
  lifetimes: {
    attached() {
      this.initTabs();
    }
  },
  observers: {
    tabs: function (tabs) {
      // 将来可能会做tabs增删改的功能(我自己想的哈哈哈哈哈)这步的意思是头一次进入页面才需要判断有无activeTab
      // 单拿出来监听tabs: activeTab的设置, 必须得在tabs赋值之后
      if (this.data.flag) return;
      if (tabs.length > 0) {
        // 代表tabs赋值完毕
        this.setData({
          flag: true,
          // 自动定位当前tab
          currentTab: this.data.activeTab === 0 ? "" : this.data.tabs[this.data.activeTab].id
        })
      }
    }
  },
})

wxss

/* 样式重点是这个容器: 宽度为本身容器的100%, 横向溢出滑动并且不能换行 */
.pane-con {
    width: 100%;
    overflow-x: scroll;
    overflow-y: hidden;
    white-space: nowrap;
}
/* 取消滚动条展示 */
.pane-con::-webkit-scrollbar {
    display: none;
}
.inline {
    display: inline-block;
}
.tabs-pane {
    padding: 10rpx 20rpx;
    margin-right: 16rpx;
    border: 1px solid lightgrey;
    border-radius: 8rpx;
    transition: all .1s ease-in;
}
.tabs-pane:nth-last-child(1) {
  margin-right: 0;
}
.tabs-pane.active {
  background: #5495df;
  border-color: #5495df;
  color: #fff;
}

使用页面代码就不放了因为是正在研发的项目, 按照注释设置参数即可.
需要传当前值的时候用trigger.event的方法将值传出去接收即可~

tada~~~一个自定义的tab就完成啦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352