程序员Web前端之路前端框架:小程序、vue、react

小程序 自定义导航栏

2019-05-28  本文已影响26人  js_hcl

一、概念

  • 上面整体就是自定义导航栏的区域(包括状态栏)
  • 胶囊接口
/*获取菜单按钮(右上角胶囊按钮)的布局位置信息。坐标信息以屏幕左上角为原点 */
wx.getMenuButtonBoundingClientRect();

/* 返回值:width、height、top、right、bottom、left*/
  • 状态栏接口
wx.getSystemInfo({
   success: e => {
     console.log(e.statusBarHeight);/*状态栏高度,如上所示*/
   }
})
height:custom.bottom +(custom.top - e.statusBarHeight);
/*即:胶囊下边界+胶囊到状态栏中间的间隔*/

二、自定义导航栏显示内容的区域

三、效果图

bgclass演示效果.png
textColor和backStyle的演示效果.png
背景图的演示.png
navBarBfc及返回及首页图标演示效果,刘亦菲是页面的image.png

四、实战代码,类似微博小程序

1.app.js部分。获取状态栏和胶囊信息

wx.getSystemInfo({
  success: e => {
    //状态栏
    let statusBarHeight= e.statusBarHeight;
    // 右上角胶囊
    let menuButton = wx.getMenuButtonBoundingClientRect();
    //胶囊宽度加上左右边距的新宽度【即自定义导航栏时,左边元素的margin-right的值】
    menuButton.extendWidth=menuButton.width+2*(e.windowWidth-menuButton.right);
    menuButton.marginRight=e.windowWidth-menuButton.right;//胶囊的右边距。用于设置返回的左边距。对称
    // 保存
    this.globalData.statusBarHeight =statusBarHeight
    this.globalData.menuButton = menuButton;  
    this.globalData.customNavBarHeight= menuButton.bottom + menuButton.top - statusBarHeight;
  }
})

globalData: {
  userInfo: null,
  //自定义导航相关的
  statusBarHeight:null,//状态栏高度
  menuButton:null,//胶囊相关数据 @obj,{width,height,top,left,right,bottom}
  customNavBarHeight:null,//自定义导航栏的高度【导航栏包括了状态栏】
}

2.组件调用

<navigationBar  bgImage="{{bgImage}}" bgClass="{{bgClass}}" textColor="{{textColor}}" 
navBarBfc="{{navBarBfc}}" backStyle="{{backStyle}}" contentText="{{contentText}}"></navigationBar>

2.导航栏组件js部分:

  • 属性说明
  • 功能介绍
// components/navigationBar/navigationBar.js
/* 
1.支持自定义导航栏类型:是否占据空间,对于页面头部是图片可以采用不占据空间类型,这样图片会从状态栏开始铺开,漂亮
2.支持导航栏背景设置为纯色,渐变色,图片【本地(本地图片要设置绝对定位,因为image标签在这里而不是使用的那个页面)、网络】或颜色背景图都有
3.支持设置内容区的文本(及icon)颜色,避免某些背景色导致看不清内容
4.支持返回类型:传统模式=>无返回,返回上一页,返回首页,返回上一页及首页
  新颖模式:自定义卡槽传入,【比如为导航球,点开垂直张开导航内容】
5.标题部分,支持正常的标题显示。或自定义<slot>【比如搜索框 等内容】
*/
const app = getApp();

Component({
  /**
   * 组件的属性列表
   * @navBarBfc 导航栏是否塌嵌(bfc):导航栏类型
   * false【default】:第一种导航栏:导航栏占据空间
   * true:第二种导航栏:导航栏不占据空间,适合头部是图片等情况 
   * 
   * @文本及icon颜色
   * @textColor://说明,标题颜色和icon颜色
   * 
   * @backStyle  返回方式 
   * "":无
   * "back"【default】:返回上一页;
   * "home":返回首页;
   * "back-home":返回上一页及返回首页
   * "new":新颖返回模式【自定义】,需要传卡槽 √
   * 
   * @contentText 标题部分 
   * 有值:导航文本;
   * 为空【default】:其它自定义内容【包括空】,需要传卡槽 √
   * 
   * @背景样式
   * @bgClass:采用背景颜色或渐变颜色,传class; 【选填】
   * @bgImage:采用背景图片;【选填】
   * 
   *@其它
   *还可以传right卡槽
   */
  externalClasses: ['bg-class'],
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },

  properties: {
    navBarBfc:{
      type:Boolean,
      value:false,//默认导航栏占据空间
    },
    textColor:{
      type:String,
      value:"#222",//默认图标及文本颜色为白色
    },
    backStyle: {
      type: String,
      default: "back",//默认返回类型:返回图标
    }, 
    contentText: {
      type:String,
      default: "",//默认标题为空
    },
    bgImage: {
      type: String,
      default: '',//默认背景图片木有
    },
  },

  /**
   * 组件的初始数据
   */
  data: {
    statusBarHeight:app.globalData.statusBarHeight,//状态栏高度
    menuButton:app.globalData.menuButton,//胶囊相关数据 @obj,{width,height,top,left,right,bottom;及extendWidth}
    customNavBarHeight:app.globalData.customNavBarHeight,//自定义导航栏的高度【导航栏包括了状态栏】
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 返回上一页
    BackPage() {
      wx.navigateBack({
        delta: 1
      });
    },
    // 返回首页
    toHome(){
      wx.reLaunch({
        url: '/pages/index/index',
      })
    }
  }
})

2.导航栏组件xml部分

<!--components/navigationBar/navigationBar.wxml-->
<!-- 整个导航栏:包括状态栏 -->
<view  style="{{navBarBfc ? '' : 'height:'+customNavBarHeight+'px;'}}">
    <!-- 避免被遮住,采用fixed定位且z-index置为最高 -->
    <view class="customBarBox">
        <!-- 背景图片 -->
        <image wx:if="{{bgImage}}" class="customBarBoxItem" style="z-index:1;width:100%;height:{{customNavBarHeight}}px" src="{{bgImage}}" />
        <!-- 导航栏内容区域:状态栏下面部分 -->
        <view class="bg-class customBarBoxItem  flex" 
        style="z-index:2;height:{{customNavBarHeight}}px;padding-top:{{statusBarHeight}}px;padding-right:{{menuButton.extendWidth}}px;font-size:34rpx;color:{{textColor}}">
            <!-- @backStyle:返回方式: -->
            <view class="flex flex0 flex-aligns-center">
                <!-- 只是显示 返回 -->
                <view wx:if="{{backStyle=='back'}}" catch:tap="BackPage">
                   <text class="iconfont icon-biaoqing" style="padding:0 30rpx;"></text>
                </view>
                <!-- 只是显示,首页 -->
                <view wx:elif="{{backStyle=='home'}}" catch:tap="toHome">
                    <text class="iconfont icon-biaoqing1" style="padding:0 30rpx;font-size:28px"></text> 
                </view>
                <!-- 显示返回及首页:类似胶囊样式 -->
                <view wx:elif="{{backStyle=='back-home'}}" class="flex flex0 flex-aligns-center flex-justifyc-center  back-home" 
                style="width:{{menuButton.width}}px;height:{{menuButton.height}}px;margin:0 
 {{menuButton.marginRight}}px;{{menuButton.marginRight}}px;">
                    <text class="iconfont icon-biaoqing" style="padding:0 10rpx;" catch:tap="BackPage"></text>
                    <text >|</text>
                    <text class="iconfont icon-biaoqing1" style="padding:0 10rpx;font-size:28px" catch:tap="toHome"></text> 
                </view>
                <!-- 采用卡槽方式 -->
                <view wx:elif="{{backStyle=='new'}}">
                    <slot name="back"></slot>
                </view>
            </view>
            <!--标题部分--><!--对齐方式:居中-->
            <view class="flex flex1 flex-aligns-center flex-justifyc-center">
                <!-- 如果是文本,超出... -->
                 <view wx:if="{{contentText}}" class="dots-1">{{contentText}}</view>
                 <!-- 传了这个卡槽就会显示 -->
                 <slot name="content"></slot>
            </view>
            <!-- right卡槽:待补充 -->
            <slot name="right"></slot>
        </view>
    </view>
</view>
<!-- 导航栏外部可携带其它组件 :如进度条,message消息等-->

3.导航栏组件css部分

  • 具体开发时,把常用类放到外部去。
  • 返回及首页icon要使用iconfont。因为这部分图标颜色要和字体颜色保持一致,可变。避免某些底色看不清
/* components/navigationBar/navigationBar.wxss */
.customBarBox{
    position: fixed;
    top:0;
    left: 0;
    right: 0;
    z-index:9999;
    /* 网格布局 */
    display: grid;
    grid-template-areas: 'main';
}
.customBarBoxItem{
   grid-area: main;
   box-sizing: border-box;
}

/* 返回及首页时样式 */
.back-home{
    border: 1px solid grey;
    background:rgba(0, 0, 0, 0.15);
    border-radius: 10000px;/* 左右半圆 */
}



/* 以下是常用布局类,放在这边好打包 */
/* flex容器常用类 */
.flex{
    display: -webkit-flex; /* Safari */
    display: flex;
}

/* 排版方向 */
.flex-direction-row{
    flex-direction: row;
}
.flex-direction-row-reverse{
    flex-direction: row-reverse;
}
.flex-direction-column{
    flex-direction: column;

}
.flex-direction-column-reverse{
    flex-direction: column-reverse;
}

/* 容器内容排版,带c代表content*/ 
/* 容器内容水平排版 */
.flex-justifyc-between{
    justify-content: space-between;
}
.flex-justifyc-center{
    justify-content: center;
}
/* 容器内容垂直排版,仅对多行时生效*/
.flex-alignc-start{
    align-content: flex-start;
}
.flex-alignc-between{
    align-content: space-between;
}
.flex-alignc-center{
    align-content: center;
}
/* 换行 */
.flex-wrap{
    flex-wrap: wrap;
    align-content: flex-start;/* 默认是stretch则每行底下平分剩余高度空间*/
}

/* 项目s内容排版,带s代表项目s */
.flex-aligns-center{
    align-items: center;
}

/* flex项目常用类 */
/* 平均放大,平均缩小 */
.flex-auto,.flex1{
    flex:auto;/*1 1 auto*/
}
/* 不放大不缩小,超出会溢出*/
.flex-none,.flex0{
    flex:none;/*0 0 auto*/
}
/* 默认,不放大,平均缩小*/
.flex-default{
     /*放大比例*/
     flex-grow: 0;
    /*缩小比例*/
    flex-shrink: 1;
    /* 主轴空间 */
    flex-basis: auto;
}
.flex-2{
    flex:2;/*放大比例系数为2,后面缺省为1 auto*/
}
/*多交叉轴自身对齐方式*/
/* flex-start | flex-end | center | baseline | stretch */
.flex-align-self-auto{
    align-self: auto;/*默认*/
}
.flex-align-self-start{
    align-self: flex-start;
}
.flex-align-self-center{
    align-self: center;
}
.flex-align-self-end{
    align-self: flex-end;
}


/* 一行多列水平垂直居中,默认水平排版,可由flex-direction来确定排版方向*/
/* 相当于针对该行,项目内容居中 */
.flex-all-center{
    justify-content: center;
    align-items: center;
}

/* 多行多列水平居中,默认水平排版,可由flex-direction来确定排版方向 */
/* 相当于针对flex容器,容器的居中 */
.flex-alls-center{
    justify-content: center;
    align-content: center;
}

/* 超出省略号... */
.dots-1{
    display:-webkit-box;
    -webkit-line-clamp:1;/* 多行改这个数字即可*/
    overflow:hidden;/*要设置容器高度,为:line-height*-webkit-line-clamp*/
    /* 否则,虽然会出现...。但如果高度较高,底下还是会展示 */
    /*如果要文字外层使用padding,则在祖父容器设置padding,父容器设置dots*/
    text-overflow:ellipsis;
    -webkit-box-orient:vertical;
    word-break:break-all;
}



/* 使用iconfont */

@font-face {font-family: "iconfont";
    src: url('iconfont.eot?t=1559543622508'); /* IE9 */
    src: url('iconfont.eot?t=1559543622508#iefix') format('embedded-opentype'), /* IE6-IE8 */
    url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAMIAAsAAAAABvAAAAK5AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqBUIFLATYCJAMMCwgABCAFhG0HPhsZBsgekiQlAQV+AEhsMCQhgmqN7Nnd20dwSA4VkERFGFAx4suHhI3RaHSEYSPyv2vZHyjNllilxGyXkmm6kGk2ZbbAksAeCEnCFdS5e6fOUYp/JfzP5fTu2rxxfstyXIPWGHrUCzAOKNAxJ1kBBcQNYxe8wM0E2o3KJB00dw6Cr8LuFYg3VLeAb8GvKCzVKtSGiQXiIzRa0478FcCH6PvxD/LDFyRNBnvg6esmO9T+7EeEsvz/2U2AQIAApzfIWAYKcdcYv6AIRle0a9Tu3KoIaanQ//9EEkNXD/rHS0QFu7gTzMNE4qefJyL4GXGFBDKoKNgEDiFp8OCQa5QWyYieZsdzxL6/fLAXFQUnt0kB1/eSFFEYfLRillaOTKa9A3D+vK9pQHnnc3ZvQPWhpIwMyeMtJTbtEGVA3icRE+48sDHoNnDwRf1lTJn/R3lZCd4O6vlzmQqVQblevbwI9/vsRy9Dp0IGPWvoJS1YvL5/QYEGHthd01v5AyCPybu/9zfuP1tfD6r83WpSAX7EvjdH+mK4rvXkjuBnSgfWFENuG3LRJJ7EcmYbNxZLaDdc/rPd/V6n64YGFxNaDWWQtBiBrNU0WkjL0OiwClWrbWi3pGV6hwGcIoofsGgDQOj1DEm375D1+oYW0gs0hv2EqjcUaHcWYQt2mA2qNXBsEdiOrDOI2pibuCahxaX9WJ9wWnheHnGHMffQEMrLzi2nWrAb8yWGeCb1fCEIIpy5UDPYDjudDBmcjWGbyB4VwijPySFNb8q2MRdo9nGYhYDZIVYzEMqGcSNBY0GrfL4fppvgZME7cHXxYRjnQVtH8mTLHYC2aNyDcI9yjcckXT5BIBCCY1yQZmDFnE6cQYzmdmMwGyHb6ISooVwOqkeGarK317n+bxO0s3fIIUuKpELrE7WwcerW/WJbHgAAAAA=') format('woff2'),
    url('iconfont.woff?t=1559543622508') format('woff'),
    url('iconfont.ttf?t=1559543622508') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
    url('iconfont.svg?t=1559543622508#iconfont') format('svg'); /* iOS 4.1- */
  }
  
  .iconfont {
    font-family: "iconfont" !important;
    font-size: 26px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  /* 返回 */
  .icon-biaoqing:before {
    content: "\e609";
  }
  /* 首页 */
  .icon-biaoqing1:before {
    content: "\e615";
  }
上一篇下一篇

猜你喜欢

热点阅读