微信小程序-自定义导航&自定义tabbar

703 阅读4分钟

自定义导航&自定义tabbar

一、自定义导航

1、创建一个自定义导航组件

思路:首先先写一个自己需要的组件,然后再使用的页面的json中注册组件,并且再页面上使用,js里面把配置的data数据配置好。如果是全部使用自定义的就在app.json中配置好,单独页面的话就再单独的页面json里面配置好即可。

在小程序的目录components 下面创建navigation-bar的组件,里面分别包含四个文件。

1677648593411.jpg

a. html

<!-- 默认为黑色的返回键-->
<view class='nav-wrap nav-bgc-class' style='height: {{statusBarHeight + navBarHeight}}px;'>
  <!--  左上角的返回按钮 其中wx:if='{{navbarData.showCapsule}}' 是控制左上角按钮的显示隐藏,1为显示,0为隐藏 -->
  <view class='nav-capsule' style='margin-top: {{statusBarHeight}}px; height: {{navBarHeight}}px;' wx:if='{{navbarData.showCapsule}}' bindtap='_navback'>
    <image class='back-pre ex-back-pre' src='{{navbarData.backSrc || "/img/back4.png"}}' mode='aspectFill'></image>
  </view>
    <!--  中间的标题 -->
  <view class='nav-title nav-title-class' style='margin-top: {{statusBarHeight}}px; height: {{navBarHeight}}px;'>{{navbarData.title}}</view>
</view>

b.json 文件

{
  "component": true
}

c.js

const app = getApp()
Component({
    // multipleSlots 为组件开启多插槽模式
    options: {
        multipleSlots: true,
    },
    // externalClasses 为组件指定多个外部样式类
    externalClasses: ['nav-bgc-class', 'nav-title-class', 'ex-back-pre'],
    // properties 组件用来储存外部数据
    properties: {
        navbarData: { //navbarData   由父页面传递的数据,变量名字自命名
            type: Object,
            value: {},
            observer: function (newVal, oldVal) {}
        },
    },
    // 组件用来储存内部私有数据
    data: {
        // 自定义导航栏的高度
        statusBarHeight: app.globalData.statusBarHeight,
        navBarHeight: app.globalData.navBarHeight
    },
    // attached函数 当组件进入页面节点树时触发,可以使用setData,绝大多数初始化工作在这个时机进行
    attached: function () {},
    // methods对象 定义组件内的各种方法
    methods: {
        // 返回键,触发自定义事件,将返回的事件交给父级页面来分情况定义
        _navback() {
            this.triggerEvent('goBack')
        }
    }
})

d.wxss

/* 顶部固定定位   标题要居中   自定义按钮和标题要和右边微信原生的胶囊上下对齐 */
.nav-wrap {
    position: fixed;
    width: 750rpx;
    top: 0;
    left: 0;
    right: 0;
    /* background: #f4f4f4; */
    background-color: pink;
    z-index: 9999999;
    transform: translate3d(0, 0, 0);
  }
   
  /* 返回键 */
  .nav-capsule {
    width: 140rpx; 
    /* 让里面的图片元素垂直居中 */
    display: flex;
    align-items: center;
  }
   
  .back-pre {
    width: 100rpx;
    height: 68rpx; 
  }
   
  /* 标题 */
  .nav-title {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    max-width: 400rpx;
    margin: auto; 
    /* 水平垂直居中 */
    display: flex;
    align-items: center;
    justify-content: space-around;
    /* 超出部分省略号显示 */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* 字体设置 */
    color: #111111;
    font-size: 32rpx;
    font-weight: 500;
  }

2、页面使用组件

a、页面json注册

{
  "usingComponents": { 
      "nav-bar": "/components/navigation-bar/navigation-bar",
      "custom-bar": "/custom-tab-bar/index"
  },
  "navigationStyle": "custom" //这个地方如果单独一个页面使用就再那个页面配置,如果不是的话可以在全局配置,但是如果全局写了这个值,就都是自定的导航了,这个地方需要注意。
}

b、页面使用

<nav-bar bind:goBack="_goBack" nav-bgc-class="ex-nav-bgc-class" nav-title-class="ex-nav-title-class" ex-back-pre="ex-back-pre" navbar-data='{{nvabarData}}'>
</nav-bar>

c、js配置数据

const app = getApp()
data:{
 // 自定义导航栏需要的参数
      nvabarData: {
          showCapsule: 0, //是否显示左上角图标   1表示显示    0表示不显示
          title: '个人中心', //导航栏 中间的标题
          backSrc: '/static/image/sy-mr1.png',// 返回键的样式
          background:null //这个地方透明就给null,其他颜色直接写背景颜色就好
      },
      // 此页面 页面内容距最顶部的距离
      height: app.globalData.statusBarHeight + app.globalData.navBarHeight,
}

3、全局配置

这里需要注意一个点,就是全局的app.js也需要获取用户的手机高度,不然返回按钮没办法和胶囊对齐。


 onLaunch() {
        var _this = this;

        //自定义导航栏 获取设备顶部窗口的高度(不同设备窗口高度不一样,根据这个来设置自定义导航栏的高度)
        wx.getSystemInfo({
            success: (res) => {
                // 基础库 2.1.0 开始支持wx.getMenuButtonBoundingClientRect(),低版本需要适配
                let custom = wx.getMenuButtonBoundingClientRect()
                // console.log('状态栏高度',res.statusBarHeight)
                // console.log('右上角胶囊按钮的高度', custom.height)
                // console.log('右上角胶囊按钮的上边界坐标', custom.top)
                // console.log('右上角胶囊按钮的下边界坐标', custom.bottom)
                _this.globalData.statusBarHeight = res.statusBarHeight
                _this.globalData.navBarHeight = custom.height + (custom.top - res.statusBarHeight) * 2
            }
        })
    },

二、自定义tabbar

1、创建组件

此处要注意的是,组件创建的位置要和最外层平级,要不不显示,我自己遇到的问题是这样的。

1677650647720.jpg

也是一样的依次是四个文件分别都写一下。或者官网拉个例子抄一下也行。

a、html

<!--miniprogram/custom-tab-bar/index.wxml-->
<cover-view class="tab-bar">
  <cover-view class="tab-bar-border"></cover-view>
  <cover-view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab">
    <cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></cover-image>
    <cover-view style="color: {{selected === index ? selectedColor : color}}">{{item.text}}</cover-view>
  </cover-view>
</cover-view>

b、js

var app = getApp();
Component({

    properties: {},
    data: {
        selected: 0,
        color: "#7A7E83", // 颜色
        selectedColor: "#FF0000", // 被选中颜色
        list: [{
            pagePath: "/pages/index/index",
            text: "首页",
            iconPath: "/static/image/sy-mr1.png",
            selectedIconPath: "/static/image/sy-xz1.png"
        }, {
            pagePath: "/pages/firstTest/index",
            text: "我的",
            iconPath: "/static/image/wd-mr2.png",
            selectedIconPath: "/static/image/wd-xz2.png"
        }],
    },
    pageLifetimes: {
        // 组件所在页面的生命周期函数

        show: () => {},

        hide: () => {}

    },
    lifetimes: {
        attached: function () {
            // 在组件实例进入页面节点树时执行 
        },
        detached: function () {
            // 在组件实例被从页面节点树移除时执行
        },
    },
    methods: {
        switchTab(e) {
            var url = e.currentTarget.dataset.path
            const data = e.currentTarget.dataset
            wx.switchTab({
                url
            })
            this.setData({
                selected: data.index
            })
        }
    }
})

c、json

{
    "component": true
}

d、wxss


.tab-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 48px;
    background: white;
    display: flex;
    padding-bottom: env(safe-area-inset-bottom);
  }
  
  .tab-bar-border {
    background-color: rgba(0, 0, 0, 0.33);
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 1px;
    transform: scaleY(0.5);
  }
  
  .tab-bar-item {
    flex: 1;
    text-align: center;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
  }
  
  .tab-bar-item cover-image {
    width: 27px;
    height: 27px;
  }
  
  .tab-bar-item cover-view {
    font-size: 10px;
  }
  


2、在使用的页面引入

json引入即可不用再页面上写组件。


{
    "usingComponents": {  
        "custom-bar": "/custom-tab-bar/index"
    }
}

最主要的是在js把页面对应上自己的index即可

 onShow() {
        if (typeof this.getTabBar === 'function' &&
        this.getTabBar()) {
        this.getTabBar().setData({
          selected: 0
        })
      }
    },