微信小程序 ---制作一个类似头条的滑动tab导航栏

效果图:
在这里插入图片描述

使用页面wxml

<!-- 顶部滑动导航栏组件 -->
<slideNav navList="{{ navList }}" fontSize="{{ 28 }}" padding="{{ 20 }}" bindtabFun="tabFun"></slideNav>

使用页面json

{
  "usingComponents": {
    "slideNav": "/component/slideNav/slideNav"
  }
}

使用页面js

// page/slideNav/slideNav.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    navList: ['关注', '推荐', '抗击肺炎', '广州', '热点', '影视', '视频', '军事', '在家上课', '动漫', '漫画', '娱乐', '国际', '科技', '正能量', '音乐', '图片', '科技', '财经', '健康', '手机', '搞笑', '法制', '职场', '情感','网球'],
  },

  tabFun(e) {
    console.log(e.detail);
  },
})

下面是组件部分

组件wxml

<scroll-view scroll-x="{{ true }}" scroll-left="{{ navLeft }}" scroll-with-animation="{{ true }}">
  <view class="nav_container">
    <block wx:for="{{ navList }}" wx:key="index">
      <view class="nav_option {{ subscript == index ? 'nav_on' : '' }}" style="padding: 0 {{ padding }}rpx; font-size: {{ fontSize }}rpx;" catchtap="tabFun" data-text="{{ item }}" data-subscript="{{ index }}">{{ item }}</view>
    </block>

    <view class="nav_line" style="width: {{ lineW }}px; transform: translateX({{ lineLeft }}px);">
      <view></view>
    </view>
  </view>
</scroll-view>

组件wxss

scroll-view {
  width: 100%;
}

.nav_container {
  display: inline-block;
  white-space: nowrap;
  background-color: #fff;
  padding-bottom: 4rpx;
  position: relative;
}

.nav_option {
  display: inline-flex;
  line-height: 50px;
}

.nav_on {
  color: red;
  font-weight: bold;
}

.nav_line {
  position: absolute;
  height: 4rpx;
  left: 0;
  bottom: 0;
  transition: all .5s;
  display: flex;
  justify-content: center;
  transform: translateX(0)
}

.nav_line>view {
  width: 50%;
  height: 100%;
  background-color: red;
}

/*隐藏滚动条*/
::-webkit-scrollbar {
  width: 0;
  height: 0;
  color: transparent;
}

组件json

{
  "component": true,
  "usingComponents": {}
}

组件js

// component/slideNav/slideNav.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    navList: {
      type: Array,
      value: '', //导航列表
    },

    fontSize: {
      type: Number,
      value: 28, //字体大小 单位rpx
    },

    padding: {
      type: Number,
      value: 20, //字体左右内边距 单位rpx
    },
  },

  /**
   * 组件的初始数据
   */
  data: {
    navLeft: 0,// 导航选项默认左偏移值
    subscript: 0,// 导航默认下标值
    lineLeft: 0,// 导航选中表示条左偏移值
  },

  lifetimes: {
    attached: function () {
      // 在组件实例进入页面节点树时执行
      this.res = wx.getSystemInfoSync();

      let { navList, fontSize, padding } = this.data;
      let pxScale = this.res.windowWidth / 750;/// 获取当前机型rpx转换px比例值
      let lineW = ((fontSize * pxScale) * navList[0].length) + (padding * pxScale) * 2;

      this.setData({ lineW });
	
	  // 返回当前导航选中下标 名称 左偏移值
      this.triggerEvent('tabFun', { subscript: 0, text: navList[0], navLeft: 0 });
    },
    detached: function () {
      // 在组件实例被从页面节点树移除时执行
    },
  },


  /**
   * 组件的方法列表
   */
  methods: {
    tabFun(e) {
      let { lineLeft, fontSize, padding } = this.data;
      let sysW = this.res.windowWidth / 2;/// 获取当前屏幕一半的值
      let pxScale = this.res.windowWidth / 750;/// 获取当前机型rpx转换px比例值
      let { offsetLeft } = e.target;// 获取当前选项左边界偏移的像素值
      let { text, subscript } = e.currentTarget.dataset;// 获取当前文字选项
      let textW = (fontSize * pxScale) * (text.length / 2);/// 获取当前选项文字一半宽度
      let aroundPadding = (padding * pxScale);/// 获取当前选项左右内边距一半的值
      let navLeft = offsetLeft - sysW + textW + aroundPadding;// 滚动条需要移动的距离
      let lineW = ((fontSize * pxScale) * text.length) + (aroundPadding * pxScale) * 2;// 选项提示线左偏移值
      
      navLeft = navLeft > 0 ? navLeft : 0;
      lineLeft = offsetLeft;

      this.setData({ navLeft, lineLeft, subscript, lineW });
		
	  // 返回当前导航选中下标 名称 左偏移值
      this.triggerEvent('tabFun', { subscript, text, navLeft });
    },
  }
})

发布了102 篇原创文章 · 获赞 75 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/sinat_19327991/article/details/105282308