微信小程序自定义头部导航nav

1.封装自定义nav导航组件

// app.js
App({
  globalData: {
    systeminfo: false,   //系统信息
    headerBtnPosi: false  //头部菜单高度
  }
})
// components/nav/nav.js
const app = getApp();
Component({
  properties: {
    vTitle: { // 标题
      type: String,
      value: ""
    },
    isSearch: {
      type: Boolean,
      value: false
    },
    noBorder: {  // 不需要下边框
      type: Boolean,
      value: false
    },
    color: { // 标题颜色
      type: String,
      value: "black"
    },
    bg: { // 背景图片路径
      type: String,
      value: ""
    },
    showBack: {  // 显示返回按钮
      type: Boolean,
      value: true
    }
  },
  data: {
    haveBack: true, // 是否有返回按钮
    statusBarHeight: 0, // 状态栏高度
    navbarHeight: 0, // 顶部导航栏高度
    navbarBtn: { // 胶囊位置信息
      height: 0,
      width: 0,
      top: 0,
      bottom: 0,
      right: 0
    },
    cusnavH: 0 //title高度
  },
  // 微信7.0.0支持wx.getMenuButtonBoundingClientRect()获得胶囊按钮高度
  attached: function () {
    if (!app.globalData.systeminfo) {
      app.globalData.systeminfo = wx.getSystemInfoSync()
    }
    if (!app.globalData.headerBtnPosi)
      app.globalData.headerBtnPosi = wx.getMenuButtonBoundingClientRect()
    let statusBarHeight = app.globalData.systeminfo.statusBarHeight // 状态栏高度
    let headerPosi = app.globalData.headerBtnPosi // 胶囊位置信息
    let btnPosi = {
      // 胶囊实际位置,坐标信息不是左上角原点
      height: headerPosi.height,
      width: headerPosi.width,
      top: headerPosi.top - statusBarHeight, // 胶囊top - 状态栏高度
      bottom: headerPosi.bottom - headerPosi.height - statusBarHeight, // 胶囊bottom - 胶囊height - 状态栏height (胶囊实际bottom 为距离导航栏底部的长度)
      right: app.globalData.systeminfo.windowWidth - headerPosi.right // 这里不能获取 屏幕宽度,PC端打开小程序会有BUG,要获取窗口高度 - 胶囊right
    }
    let haveBack
    if (this.properties.showBack === false) {
      haveBack = false
    } else {
      haveBack = true
    }
    
    var cusnavH = btnPosi.height + btnPosi.top + btnPosi.bottom // 导航高度
    this.setData({
      haveBack: haveBack, // 获取是否是通过分享进入的小程序
      statusBarHeight: statusBarHeight,
      navbarHeight: headerPosi.bottom + btnPosi.bottom, // 胶囊bottom + 胶囊实际bottom
      navbarBtn: btnPosi,
      cusnavH: cusnavH
    })
    //将实际nav高度传给父类页面
    this.triggerEvent("commonNavAttr", {
      height: headerPosi.bottom + btnPosi.bottom
    })
  },
  methods: {
    _goBack: function () {
      wx.navigateBack({
        delta: 1
      })
    },
    bindKeyInput: function (e) {
      // console.log(e.detail.value);
    }
  }
})
// components/nav/nav.json
{
  "component": true,
  "usingComponents": {},
  "navigationStyle": "custom"
}

<view class="custom_nav" style="height:{{navbarHeight}}px;position: relative;">
  <image wx:if="{{ !!bg }}" class="head-bg" mode="widthFix" src="{{bg}}">image>
  <view class="custom_nav_box {{noBorder?'no-border':''}}" style="height:{{navbarHeight}}px;">
    <view class="custom_nav_bar" style="top:{{statusBarHeight}}px; height:{{cusnavH}}px;">
      <block wx:if="{{isSearch}}">
        <input class="navSearch" style="height:{{navbarBtn.height-2}}px;line-height:{{navbarBtn.height-4}}px; top:{{navbarBtn.top+1}}px; left:{{navbarBtn.right}}px; border-radius:{{navbarBtn.height/2}}px;" maxlength="10" bindinput="bindKeyInput" placeholder="输入文字搜索"/>
      block>
      <block wx:else>
        <view class="custom_nav_icon" style="height:{{navbarBtn.height}}px;line-height:{{navbarBtn.height-2}}px; top:{{navbarBtn.top}}px; left:{{navbarBtn.right}}px;">
          <view wx:if="{{haveBack}}" class="icon-back" bindtap='_goBack'>
            
            <iconfont name="back" color="#ff6200" size="44"/>
          view>
        view>
        <view class="nav_title" style="color: {{color}};height:{{cusnavH}}px; line-height:{{cusnavH}}px;">
          {{vTitle}}
        view>
      block>
    view>
  view>
view>
/* components/nav/nav.wxss*/
.custom_nav {
  width: 100%;
  position: relative;
}

.head-bg {
  position: fixed;
  top: 0;
  left: 0;
  z-index: -1;
  width: 100%;
}
.custom_nav_box {
  position: fixed;
  width: 100%;
  z-index: 99999;
  border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
  box-shadow: 2rpx 2rpx 12rpx 0rpx rgba(95,95,95,0.1);
}
.custom_nav_box.no-border {
  border-bottom: none;
  box-shadow: none;
}

.custom_nav_bar {
  position: relative;
  z-index: 9;
}

.custom_nav_box .nav_title {
  font-size: 30rpx;
  text-align: center;
  position: absolute;
  max-width: 360rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  z-index: 1;
}

.custom_nav_box .custom_nav_icon {
  position:absolute;
  z-index: 2;
  display: inline-block;
  border-radius: 50%;
  vertical-align: top;
  font-size:0;
  box-sizing: border-box;
}
.custom_nav_box .custom_nav_icon.borderLine {
  border: 1rpx solid rgba(255, 255, 255, 0.3);
  background: rgba(0, 0, 0, 0.1);
}

.navbar-v-line {
  width: 1px;
  margin-top: 14rpx;
  height: 32rpx;
  background-color: rgba(255, 255, 255, 0.3);
  display: inline-block;
  vertical-align: top;
}

.icon-back {
  display: flex;
  align-items: center;
  width: 74rpx; 
  padding-left: 20rpx;
  height: 100%;
}

.icon-home {
  display: inline-block;
  width: 80rpx;
  text-align: center;
  vertical-align: top;
  height: 100%;
}

.icon-home .home_a {
  height: 100%;
  display: inline-block;
  vertical-align: top;
  width: 35rpx;
}

.custom_nav_box .back-pre,
.custom_nav_box .back-home {
  width: 40rpx;
  height: 40rpx;
}

.navSearch {
  width: 200px;
  background: #fff;
  font-size: 14px;
  position: absolute;
  padding: 0 20rpx;
  z-index: 9;
}

2.修改全局配置

navigationStyle 字段设置为 custom,这样就能使用自定义的nav。

// app.json
"window": {
  "backgroundTextStyle": "light",
  "navigationBarBackgroundColor": "#fff",
  "navigationBarTitleText": "测试",
  "navigationBarTextStyle": "black",
  "navigationStyle": "custom"
},

3.页面使用

需要使用自定义nav的页面,需要每个页面都要引入自定义组件:

// pages/service/service.json
{
  "usingComponents": {
    "nav-component": "/components/nav/nav"
  }
}

<nav-component v-title="服务" showBack="{{ false }}">nav-component>

效果:
微信小程序自定义头部导航nav_第1张图片
显示返回按钮,具体样式可以在自定义组件中定义默认样式:

<nav-component v-title="订单详情">nav-component>

微信小程序自定义头部导航nav_第2张图片
复杂一点的头部带背景图片:

<nav-component 
  v-title="首页" 
  color="white" 
  bg="/res/images/home_bg.png"
  no-border="{{ true }}"
  showBack="{{false}}"
>nav-component>

微信小程序自定义头部导航nav_第3张图片

你可能感兴趣的:(微信小程序Weapp,微信小程序,小程序,前端,自定义nav)