小程序- 自定义导航栏组件封装
小程序开发的头部设计组件。
custom-navbar.json
{ "component": true, "usingComponents": {} }
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'); } } });
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>
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%; }
<custom-navbar title="首页" backgroundColor="#ffffff" titleColor="#333333" showBack="{{false}}" showHome="{{true}}" bind:back="onBack" bind:more="onMore" /> <!-- 页面内容 --> <view class="page-content"> <!-- 你的页面内容 --> </view>
如需转载原创文章,请标注原文地址,版权所有!
浙公网安备 33010602011771号