评论

小程序顶部自定义导航组件实现原理及坑分享

小程序顶部自定义导航组件实现原理分析,附上组件源码及示例学习交流。

为什么使用自定义导航

对比默认导航栏,我们会更需要:

  • 统一Android、IOS手机对于页面title的展示样式及位置
  • 更丰富的导航栏定制效果,如添加home图标等
  • 左上角返回事件的监听处理
  • 统一实现双击返回顶部功能

自定义导航组件实现思路

自定义导航组件实现的核心是需要计算导航栏的真实高度

这里以官方文档->扩展能力中的Navigation组件为例分析实现思路。当使用"navigationStyle": "custom"时,默认导航被移除,页面的开始位置变成了屏幕顶部,这时我们需要实现的导航栏是在状态栏下面。

导航栏的真实高度=状态栏高度+导航栏内容。

使用wx.getSystemInfo获取到statusBarHeight便是导航栏的高度,但是导航栏内容高度呢?

有人可能觉得导航栏内容高度顾名思义就是导航栏内容高度啊,内容撑起还用管嘛!要,必须要!
因为右上角胶囊按钮是原生加载的,我们的导航栏内容需要正好贴在胶囊的下方且垂直居中。

导航栏内容高度=(胶囊按钮的顶部距离 - 状态高度)*2 + 胶囊高度

如何计算胶囊的数据呢?幸运的是我们有 wx.getMenuButtonBoundingClientRect() 获取胶囊按钮的布局位置信息,那么动态计算导航栏的内容高度就很方便啦。
好了,以上就是动态计算的核心思路,我们再来看官方Navigation组件高度是怎么实现的

page{--height:44px;--right:190rpx;}
.weui-navigation-bar .android{--height:48px;--right:222rpx}
.weui-navigation-bar__inner{
	position:fixed;top:0;left:0;z-index:5001;display:flex;align-items:center;
	height:var(--height);padding-right:var(--right);width:calc(100% - var(--right))
}

导航栏内容的高度是通过- -height这个css变量提前声明好的,安卓机型会重新覆盖为新的css变量值,目前没发现有适配问题。
官方就是官方啊,具体尺寸都知道,那就不用一番计算周折啦,直接拿来主义即可。
导航的布局位置已经搞定啦,剩下就是写具体的内容,不同业务实现需求不同这里就不一一赘述了。

完善官方顶部导航组件

本着拿来主义,直接使用官方Navigation组件,但在实际业务开发中还是遇到不少需要自定义的需求,就比如:

  • loadding样式没实现
  • 标题内容超出没有出现省略号
  • 和原生顶部的样式不兼容,导致单个页面引入时跳转有明显差异出现
  • 没有双击返回顶部功能开关功能
  • 引入页面需要获取导航栏的高度,来控制其他元素距离顶部的位置,
  • 不能根据页面栈数据动态显示隐藏back按钮,

针对以上需求,我们对官方的组件进行二次完善开发,满足常规的自定义需求绰绰有余,直接引入开箱即用。
源码使用示例 https://github.com/YuniorZen/minicode-debug/tree/master/minicode02

使用说明

/*自定义头部导航组件,基于官方组件Navigation开发。*/

<navigation-bar title="会员中心" bindgetBarInfo="getBarInfo"></navigation-bar>

组件属性列表

属性 类型 描述
bindgetBarInfo function 组件实例载入页面时触发此事件,首参为event对象,event.detail携带当前导航栏信息,如导航栏高度 event.detail.topBarHeight
bindback function 点击back按钮触发此事件响应函数
backImage string back按钮的图标地址
homeImage string home按钮的图标地址
ext-class string 添加在组件内部结构的class,可用于修改组件内部的样式
title string 导航标题,如果不提供为空
background string 导航背景色,默认#ffffff
color string 导航字体颜色
dbclickBackTop boolean 是否开启双击返回顶部功能,默认true
border boolean 是否显示顶部导航下边框分割线,默认false
loading boolean 是否显示标题左侧的loading,默认false
show boolean 显示隐藏导航,隐藏的时候navigation的高度占位还在,默认true
left boolean 左侧区域是否使用slot内容,默认false
center boolean 中间区域是否使用slot内容,默认false

Slot

name 描述
left 左侧slot,在back按钮位置显示,当left属性为true的时候有效
center 标题slot,在标题位置显示,当center属性为true的时候有效

自定义顶部导航目前存在的坑

  • 弹窗的背景蒙层无法覆盖原生胶囊按钮
  • 页面下拉刷新的圆点会被自定义导航遮盖

如果要自定义顶部导航,以上问题避免不了,只能忍着接受。
目前还没遇到完美的解决方案,针对下拉刷新圆点被遮挡的问题微信官方还在需求开发中,如果你有好的想法欢迎留言反馈,一起学习交流。

最后一次编辑于  2019-10-31  
点赞 17
收藏
评论

11 个评论

  • Yunior
    Yunior
    2020-12-12

    2020.12.12 更新

    不知为何,源文章编辑无法发表,只好在评论处更新一下。

    最近在实践项目中发现,封装组件过于细节的设置会限制组件的使用场景,可扩展性比较低。

    所以重新另做一个 <navigation-bar-simple> 简版的组件。

    一是修复评论处提出的兼容问题;二是组件只做了顶部导航的框架处理,具体左边和中间放置什么内容,通过slot插入即可,提供外部类控制样式,提供隐藏和双击返回顶部的基础api。

    2020-12-12
    赞同 1
    回复
  • Frost
    Frost
    01-10

    自定义导航栏标题的字体大小要设置多少呢

    01-10
    赞同
    回复
  • 三毛
    三毛
    2022-05-24

    ---我们的导航栏内容需要正好贴在胶囊的下方且垂直居中。---

    胶囊的下方为什么是下方,说的是左方吧?

    2022-05-24
    赞同
    回复
  • 波吉
    波吉
    2021-03-22

    头大

    2021-03-22
    赞同
    回复
  • 白俊鹏
    白俊鹏
    2020-07-08

    有个疑问,胶囊宽高不是固定死的吗,为什么还要用api去获取呢?

    2020-07-08
    赞同
    回复 2
    • Yunior
      Yunior
      2020-07-14
      用API获取的精准,摸不准哪天尺寸调整了
      2020-07-14
      回复
    • 枫
      2022-04-20
      不同型号手机下是不一样的,Android(小米 11) 明显比 iOS(12 Pro) 下的尺寸要大
      2022-04-20
      回复
  • 哈罗哈皮
    哈罗哈皮
    2020-03-02

    楼主,同样的代码为何不一样?求解

    2020-03-02
    赞同
    回复 5
    • smile face reality
      smile face reality
      2020-06-02
      请问这个问题好了没,遇到同样问题,但是我的是偶尔出现
      2020-06-02
      回复
    • 哈罗哈皮
      哈罗哈皮
      2020-06-02回复smile face reality
      我忘记了,现在 没有用,你可以看看他写的源码,能自己定位
      2020-06-02
      回复
    • smile face reality
      smile face reality
      2020-06-02回复哈罗哈皮
      好的谢谢
      2020-06-02
      回复
    • Yunior
      Yunior
      2020-07-14
      确实有部分兼容问题,我回头更新一下,采用动态获取更精准,官方给出的头部导航的内容高度还是有些问题。
      2020-07-14
      回复
    • Yunior
      Yunior
      2020-12-12
      可能是inner元素盒子模型被定位成了border-box, 修改样式box-sizing:content-box;
      2020-12-12
      回复
  • 2019-12-10

    用了自定义导航,左上角返回键有的时候需要点很多次 才能返回。有的时候点一次就返回

    2019-12-10
    赞同
    回复 4
    • Yunior
      Yunior
      2019-12-10
      你好,最好分享个代码片段给你看一下,确认一下是因为点击区域不中的问题还是事件跳转的问题,如果点击区域过小问题,可以看这里放大点击区域解决 https://developers.weixin.qq.com/community/develop/article/doc/000240284cc6880feb590fde15b413
      2019-12-10
      回复
    • 2019-12-13回复Yunior
      我点击后,出了点击效果,但是没有返回,需要点很多次。或者连续点两次就返回,所有手机都是这样。用的是WEUI的自定义导航
      2019-12-13
      回复
    • Yunior
      Yunior
      2019-12-22回复
      WEUI的代码我之前定制开发的时候,好像也遇到过这个问题,后来放大了点击区域就没有问题了,你可以试试看。
      2019-12-22
      回复
    • JIn
      JIn
      2020-01-15
      用了这个组件以后,你的运维查询中的错误查询有没有wx.getMenuButtonBoundingClientRect这个方法的错误。
      2020-01-15
      回复
  • TNT
    TNT
    2019-11-27

    第二个问题。昨天的【腾讯QQ】小程序貌似解决了?

    2019-11-27
    赞同
    回复 1
  • liang――
    liang――
    2019-11-07

    楼主,不是说自定义顶部导航栏之后,没有下拉刷新的操作了吗?

    2019-11-07
    赞同
    回复 1
    • Yunior
      Yunior
      2019-11-08
      操作有的,只是圆点被导航遮挡了
      2019-11-08
      回复
  • One Eight Nine Four
    One Eight Nine Four
    2019-10-26

    之前看过一个小程序,自定义导航栏后,下拉刷新是用gif图片来做的.

    2019-10-26
    赞同
    回复 3
    • Yunior
      Yunior
      2019-10-26
      好奇是怎么做到的,请问是哪款小程序还记得嘛
      2019-10-26
      回复
    • One Eight Nine Four
      One Eight Nine Four
      2019-10-26回复Yunior
      二更视频.
      2019-10-26
      回复
    • Yunior
      Yunior
      2019-10-26回复One Eight Nine Four
      谢谢,我去学习下
      2019-10-26
      回复

正在加载...

登录 后发表内容