uniapp——自定义导航栏的封装

为什么需要封装自定义导航

  1. 首先如果开发的是微信小程序,那么在安卓环境下导航栏标题是默认靠左对齐的(虽然你在微信开发者工具上看到的依旧是居中展示),而在ios环境则是居中展示的。
  2. 很多时候我们需要对整个项目有一个主题色或者公共的样式配置,封装一个公共的自定义导航栏更易于实现与管理。
  3. 系统导航栏高度根据机型会发生变化,大部分是44px,但是有时候也会是40px等高度,如果你需要针对导航栏和状态栏高度对页面做一些定制需求那会显得比较困难。(网上有一些根据胶囊按钮获取导航栏高度的方法实测后发现并不精准。)

当然原生导航也并不是一无是处的。原生导航的体验更好,渲染新页面时,原生导航栏的渲染无需等待新页面dom加载,可以在新页面进入动画开始时就渲染。原生导航还可以避免滚动条通顶,并方便的控制原生下拉刷新。

封装思路

这里我们借助uniapp官方提供的uni-nav-bar进行封装。(vue3 + ts + setup)

  1. 首先,我们希望可以自动获取每个页面的标题,并不是每次使用自定义组件再去设置,我们置顶page.json里面包含了我们所有的页面的标题,所以我们直接导入该文件,使用currentPage获取当前页面的路由,然后匹配page.json文件里面的page或者subPackages路由,需要注意的是subPackages里面的路由需要自己收到拼装。

    js 复制代码
    const { title, ...$attrs } = useAttrs()
    const defaultTitle = '我是默认标题'
    // 通过page.json文件里面的pages与subPackages数组自动获取标题栏
    const getCurrentPageTitle = () => {
      // 有传入的标题直接使用传入的标题
      if (title) {
        return title
      }
      const { route } = currentPage()
      const page = pagesjson.pages.find((item) => item.path === route)
      if (page) {
        return page.style?.navigationBarTitleText || defaultTitle
      }
      for (const subPackage of pagesjson.subPackages) {
        const subPage = subPackage.pages?.find(
          (item) => route === `${subPackage.root}/${item.path}`
        )
        if (subPage) {
          return subPage.style?.navigationBarTitleText || defaultTitle
        }
      }
    }
  2. 然后我们使用getCurrentInstance和``createSelectorQuery定义一个方法返回自定义导航栏的高度,便于我们需要的时候使用。

    js 复制代码
    const pageInstace = getCurrentInstance()
    const emits = defineEmits(['getHeight'])
    onMounted(() => {
      const query = uni.createSelectorQuery().in(pageInstace?.proxy)
      query
        .select('.uniNavBar')
        .boundingClientRect((data: any) => {
          emits('getHeight', data.height + 'px')
        })
        .exec()
    })
  3. 最后我们还需使用$attrs对组件的属性方法进行穿透,这在我们对组件进行二次封装的时候应该都是必须要做的操作。

完整代码

js 复制代码
<template>
  <uni-nav-bar
    class="uniNavBar"
    v-bind="$attrs"
    :border="border"
    :statusBar="statusBar"
    :fixed="fixed"
    :leftIcon="leftIcon"
    :title="getCurrentPageTitle()"
    @clickLeft="clickLeft"
  ></uni-nav-bar>
</template>

<script lang="ts" setup>
import { onMounted, getCurrentInstance } from 'vue'
import { useAttrs } from 'vue'
import pagesjson from '@/pages.json'
import { currentPage } from '@/utils/tools'

interface Props {
  border?: boolean
  statusBar?: boolean
  fixed?: boolean
  leftIcon?: string
}

const props = withDefaults(defineProps<Props>(), {
  border: false,
  statusBar: true,
  fixed: true,
  leftIcon: 'left',
})

const { title, ...$attrs } = useAttrs()
const pageInstace = getCurrentInstance()
const emits = defineEmits(['getHeight'])
onMounted(() => {
  const query = uni.createSelectorQuery().in(pageInstace?.proxy)
  query
    .select('.uniNavBar')
    .boundingClientRect((data: any) => {
      emits('getHeight', data.height + 'px')
    })
    .exec()
})

const defaultTitle = '我是默认标题'
// 通过page.json文件里面的pages与subPackages数组自动获取标题栏
const getCurrentPageTitle = () => {
  // 有传入的标题直接使用传入的标题
  if (title) {
    return title
  }
  const { route } = currentPage()
  const page = pagesjson.pages.find((item) => item.path === route)
  if (page) {
    return page.style?.navigationBarTitleText || defaultTitle
  }
  for (const subPackage of pagesjson.subPackages) {
    const subPage = subPackage.pages?.find(
      (item) => route === `${subPackage.root}/${item.path}`
    )
    if (subPage) {
      return subPage.style?.navigationBarTitleText || defaultTitle
    }
  }
}

// navbar返回按钮事件
const clickLeft = () => {
  uni.navigateBack()
}
</script>
相关推荐
Dumbness2 天前
订阅消息弹窗必须在用户点击里调:联调实验室里 timing 和 Mock 支付通知踩的坑
javascript·uni-app
码间留白3 天前
uni-app 鸿蒙离线打包:一个改动从源码到真机要穿过几条链
uni-app·鸿蒙·deveco·离线打包·uts插件
多客:duokelijie4 天前
代练订单系统选型思路:跨品类游戏接入、订单分层管理、自动结算逻辑拆解!
数据库·mysql·微信小程序·前端框架·uni-app·php·持续部署
码间留白4 天前
鸿蒙端对接 BLE 血压计:从一次握手到读数入库(二)设备篇
物联网·uni-app·鸿蒙·蓝牙ble·血压计
华玥作者5 天前
Vue 3 + TypeScript + uni-app 组件库推荐:hy-app(华玥组件库)
vue.js·typescript·uni-app
FinelyYang5 天前
uniapp使用kkfileview在线预览ppt,excel,word,pdf类型文件
pdf·uni-app·powerpoint
2501_916008895 天前
iPhone 设备信息查看,用 KeyMob 看型号、序列号、电池健康和 UDID
android·ios·小程序·https·uni-app·iphone·webview
ModyQyW6 天前
vite-plugin-uni-manifest 0.7:在 uni-app 读取之前生成
前端·uni-app
lyz2468596 天前
uniapp vue3 小程序开发注意事项
uni-app
雪芽蓝域zzs6 天前
WebStorm Uniapp Support + Uniapp Tool + Uniappx Language Service讲解
vue.js·uni-app·webstorm