微信小程序使用 swiper 制作 tabbar

440 阅读1分钟

主要是微信官方的自定义 tabbar 会出现闪烁的问题,强迫症犯了

效果图

1.gif

不过这样做也有许多缺点,比如用不了页面生命周期函数了,并且导航栏也需要自定义

自定义组件目录

image.png

tab 组件
Component({
  properties: {
    name: String, // 标签名
    icon: String, // 标签图标
    key: String, // 标签键
    color: String, // 标签字体颜色
    bgColor: String, // 标签背景颜色
  },
  data: {},

  relations: {
    "../tabs/index": {
      type: "parent",
    },
  },
  methods: {},
});
<view class="tabbar-item">
  <slot></slot>
</view>
tabs 组件
Component({
  properties: {},

  // 启用多 slot 支持
  options: {
    multipleSlots: true,
  },

  relations: {
    "../tab/index": {
      type: "child",
    },
  },

  data: {
    selected: 0,
    pages: [],
  },

  methods: {
    switchTab(e) {
      this.setData({
        // 页面切换
        selected: e.currentTarget.dataset.index,
      });
    },
    swiperChage(e) {
      this.setData({
        // 页面切换
        selected: e.detail.current,
      });
    },
    _initTabs() {
      // 获取关联的子节点
      let nodes = this.getRelationNodes("../tab/index");

      let pages = nodes.map((e) => e.data);

      this.setData({
        pages,
      });
    },
  },

  ready() {
    // 初始化轮播图和 tabber
    this._initTabs();
  },
});
<view>
  <!-- 轮播图实现页面切换 -->
  <swiper current="{{selected}}" bindchange="swiperChage">
    <swiper-item
      wx:for="{{pages}}"
      wx:key="index"
    >
      <!-- 页面 -->
      <slot name="{{item.key}}" />
    </swiper-item>
  </swiper>
  <!-- 底部 tabbar -->
  <cover-view class="tab-bar">
    <cover-view
      wx:for="{{pages}}"
      wx:key="index"
      class="tab-bar-item {{selected === index ? 'active' : ''}} {{item.color}}"
      style="{{selected === index ? 'color: ' + item.color + ';background-color: ' + item.bgColor:''}}"
      data-index="{{index}}"
      bindtap="switchTab"
    >
      <!-- 图标 -->
      <cover-view class="iconfont {{item.icon}} icon" />
      <!-- 文字 -->
      <cover-view class="tab-name">{{item.name}}</cover-view>
    </cover-view>
  </cover-view>
</view>
@import "../../../styles/iconfont.wxss";

/* 页面样式 */
swiper {
  height: 100vh;
  width: 100vw;
}

/* tabbar 样式 */
.tab-bar {
  padding: 0.5em 1em;
  padding-bottom: env(safe-area-inset-bottom, 00.3em);
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(10px);
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 3em;
  display: flex;
  justify-content: space-between;
}

.tab-bar-item {
  border-radius: 50px;
  transition: background-color 0.4s linear;
  margin: 0 0.5em;
  padding: 0 1em;
  display: flex;
  justify-content: center;
  align-items: center;
}

.icon {
  font-size: 1.2em;
}

.tab-name{
  font-weight: bold;
  overflow: hidden;
  max-width: 0;
}

.tab-bar-item.active .tab-name {
  margin-left: 10px;
  max-width: 200px;
  transition: max-width 1s linear;
}
使用
{
  "usingComponents": {
    "tab-bar": "/components/tabbar/tabs",
    "tab-bar-item": "/components/tabbar/tab"
  }
}
<tab-bar>
  <tab-bar-item
    key="home"
    name="首页"
    icon="home"
    bgColor="rgba(230, 169, 25, 0.2)"
    color="#e6a919"
    slot="home"
  >
  <!-- 页面1 -->
  <view style="background: LightSkyBlue" class="view">1</view>
  </tab-bar-item>
  
  <tab-bar-item
    key="like"
    name="收藏"
    icon="like"
    bgColor="rgba(201, 55, 157, 0.2)"
    color="#c9379d"
    slot="like"
  >
  <!-- 页面2 -->
  <view style="background: LightCyan" class="view">2</view>
  </tab-bar-item>
  
  <tab-bar-item
    key="me"
    name="我的"
    icon="me"
    bgColor="rgba(28, 150, 162, 0.2)"
    color="#1c96a2"
    slot="me"
  >
  <!-- 页面2 -->
  <view style="background: Moccasin" class="view">3</view>
  </tab-bar-item>
</tab-bar>