小程序- 自定义导航栏组件封装

小程序开发的头部设计组件。

custom-navbar.json

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

custom-navbar.js

Component({
  properties: {
    // 导航栏标题
    title: {
      type: String,
      value: ''
    },
    // 标题颜色
    titleColor: {
      type: String,
      value: '#000000'
    },
    // 背景颜色
    backgroundColor: {
      type: String,
      value: '#ffffff'
    },
    // 背景图片
    backgroundImage: {
      type: String,
      value: ''
    },
    // 是否显示返回按钮
    showBack: {
      type: Boolean,
      value: true
    },
    // 返回按钮颜色
    backIconColor: {
      type: String,
      value: '#000000'
    },
    // 返回按钮图标
    backIcon: {
      type: String,
      value: 'default' // default | custom
    },
    // 自定义返回图标路径
    customBackIcon: {
      type: String,
      value: ''
    },
    // 是否显示首页按钮
    showHome: {
      type: Boolean,
      value: false
    },
    // 是否显示更多按钮
    showMore: {
      type: Boolean,
      value: false
    },
    // 是否固定在顶部
    fixed: {
      type: Boolean,
      value: true
    },
    // 是否占位(fixed时有效)
    placeholder: {
      type: Boolean,
      value: true
    },
    // 自定义导航栏高度(单位px)
    navBarHeight: {
      type: Number,
      value: 0
    },
    // 是否透明背景
    transparent: {
      type: Boolean,
      value: false
    }
  },

  data: {
    statusBarHeight: 0,
    navBarHeightCalc: 44,
    totalHeight: 0,
    capsuleWidth: 0
  },

  lifetimes: {
    attached() {
      this.initNavBar();
    }
  },

  methods: {
    // 初始化导航栏
    initNavBar() {
      try {
        // 获取系统信息
        const systemInfo = wx.getSystemInfoSync();
        const statusBarHeight = systemInfo.statusBarHeight;
        
        // 获取胶囊按钮信息
        const menuButtonInfo = wx.getMenuButtonBoundingClientRect();
        
        // 计算导航栏高度
        // 导航栏高度 = 胶囊按钮高度 + 上下间距
        const navBarHeightCalc = (menuButtonInfo.top - statusBarHeight) * 2 + menuButtonInfo.height;
        
        // 计算总高度
        const totalHeight = statusBarHeight + navBarHeightCalc;
        
        // 计算胶囊按钮宽度(用于右侧留白)
        const capsuleWidth = systemInfo.windowWidth - menuButtonInfo.left;
        
        this.setData({
          statusBarHeight,
          navBarHeightCalc: this.properties.navBarHeight || navBarHeightCalc,
          totalHeight,
          capsuleWidth
        });
      } catch (error) {
        console.error('初始化导航栏失败', error);
        // 默认值(适配大多数设备)
        this.setData({
          statusBarHeight: 20,
          navBarHeightCalc: 44,
          totalHeight: 64,
          capsuleWidth: 100
        });
      }
    },

    // 返回上一页
    onBack() {
      const pages = getCurrentPages();
      if (pages.length > 1) {
        wx.navigateBack({
          delta: 1
        });
      } else {
        this.triggerEvent('back');
      }
    },

    // 返回首页
    onHome() {
      wx.switchTab({
        url: '/pages/index/index'
      });
    },

    // 更多按钮点击
    onMore() {
      this.triggerEvent('more');
    },

    // 标题点击
    onTitleTap() {
      this.triggerEvent('titleTap');
    }
  }
});
View Code

custom-navbar.wxml

<view class="navbar-container {{fixed ? 'fixed' : ''}}" 
      style="background-color: {{backgroundColor}}; background-image: url('{{backgroundImage}}');">
  
  <!-- 状态栏占位 -->
  <view class="status-bar" style="height: {{statusBarHeight}}px;"></view>
  
  <!-- 导航栏内容 -->
  <view class="nav-bar" style="height: {{navBarHeightCalc}}px;">
    
    <!-- 左侧区域 -->
    <view class="nav-left" style="width: {{capsuleWidth}}px;">
      <!-- 返回按钮 -->
      <view class="back-btn" wx:if="{{showBack}}" bindtap="onBack">
        <block wx:if="{{backIcon === 'default'}}">
          <view class="back-arrow" style="border-color: {{backIconColor}};"></view>
        </block>
        <block wx:elif="{{backIcon === 'custom' && customBackIcon}}">
          <image class="custom-icon" src="{{customBackIcon}}" mode="aspectFit"></image>
        </block>
      </view>
      
      <!-- 首页按钮 -->
      <view class="home-btn" wx:if="{{showHome}}" bindtap="onHome">
        <text class="home-icon" style="color: {{backIconColor}};">⌂</text>
      </view>
    </view>
    
    <!-- 中间标题 -->
    <view class="nav-center" bindtap="onTitleTap">
      <text class="nav-title" style="color: {{titleColor}};">{{title}}</text>
    </view>
    
    <!-- 右侧区域 -->
    <view class="nav-right" style="width: {{capsuleWidth}}px;">
      <!-- 更多按钮 -->
      <view class="more-btn" wx:if="{{showMore}}" bindtap="onMore">
        <view class="more-dot" style="background-color: {{backIconColor}};"></view>
        <view class="more-dot" style="background-color: {{backIconColor}};"></view>
        <view class="more-dot" style="background-color: {{backIconColor}};"></view>
      </view>
    </view>
  </view>
</view>

<!-- 占位元素(fixed时有效) -->
<view class="navbar-placeholder" 
      wx:if="{{fixed && placeholder}}" 
      style="height: {{totalHeight}}px;"></view>
View Code

wxsscustom-navbar.wxss

.navbar-container {
  width: 100%;
  background-size: cover;
  background-position: center;
  z-index: 9999;
}

.navbar-container.fixed {
  position: fixed;
  top: 0;
  left: 0;
}

.status-bar {
  width: 100%;
}

.nav-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 10rpx;
  box-sizing: border-box;
}

/* 左侧区域 */
.nav-left {
  display: flex;
  align-items: center;
  padding-left: 20rpx;
  box-sizing: border-box;
}

.back-btn {
  width: 60rpx;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.back-arrow {
  width: 20rpx;
  height: 20rpx;
  border-left: 4rpx solid;
  border-bottom: 4rpx solid;
  transform: rotate(45deg);
  margin-left: 8rpx;
}

.custom-icon {
  width: 40rpx;
  height: 40rpx;
}

.home-btn {
  width: 60rpx;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 10rpx;
}

.home-icon {
  font-size: 40rpx;
}

/* 中间标题 */
.nav-center {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 0 20rpx;
}

.nav-title {
  font-size: 34rpx;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* 右侧区域 */
.nav-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 20rpx;
  box-sizing: border-box;
}

.more-btn {
  width: 60rpx;
  height: 60rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6rpx;
}

.more-dot {
  width: 8rpx;
  height: 8rpx;
  border-radius: 50%;
}

/* 占位元素 */
.navbar-placeholder {
  width: 100%;
}
View Code

 

<custom-navbar
  title="首页"
  backgroundColor="#ffffff"
  titleColor="#333333"
  showBack="{{false}}"
  showHome="{{true}}"
  bind:back="onBack"
  bind:more="onMore"
/>

<!-- 页面内容 -->
<view class="page-content">
  <!-- 你的页面内容 -->
</view>

 

posted @ 2026-06-02 14:39  微宇宙  阅读(2)  评论(0)    收藏  举报