uniapp微信小程序封装navbar组件

0 阅读3分钟

一、 最终效果

在这里插入图片描述

二、实现了功能

1、nav左侧返回icon支持自定义点击返回事件(默认返回上一步)
2、nav左侧支持既显示返回又显示返回首页icon
3、nav左侧只显示返回icon
4、nav左侧只显示返回首页icon
5、nav左侧自定义left插槽
6、nav中间支持title命名
7、nav中间支持center插槽
8、支持自定义背景颜色:backgroundColor
9、支持修改icon大小、颜色
10、支持导航栏文字颜色自定义
11、支持自定义返回指定页面并可以传参(goBackUrl、urlParam)
12、支持自定义导航栏高度(默认设备高度)

三、navbar参数配置

1、代码示例:

<navbar titleText="登录页面"/>

2、 配置参数(Attributes)

参数说明类型默认值
backgroundColor导航栏背景颜色String#355db4
navCustomHeight自定义导航栏高度(单位rpx)number0
color导航栏文字颜色String#fff
fontSize导航栏文字大小(单位rpx)number32
iconSize导航栏图标大小number18
iconColor导航栏图标颜色String#fff
titleText导航栏标题String-
backMain是否显示返回首页图标booleanfalse
isGoBack是否显示返回图标booleanfalse
isGoBackEvent是否自定义写返回事件booleanfalse
goBackUrl返回指定页面路径string-
urlParam返回指定页面路径参数string-

3、 Events

事件名说明返回值
goBack自定义返回事件-

4、Slot

事件名说明
left左侧具名插槽
center导航栏标题插槽)
-默认插槽

四、源码

<template>
  <view class="nav" :style="navStyle">
    <view :style="statusBarStyle"></view>
    <view class="navBar" :style="navBarStyle">
      <view class="nav_bar_left" :style="{ color }">
        <!-- 既显示返回又显示返回首页icon -->
        <view v-if="isGoBack && backMain" class="back-home">
          <view class="back flex-box flex-ver" @tap="goBack">
            <uni-icons class="imageClass" :size="iconSize" type="left" :color="iconColor"></uni-icons>
          </view>
          <view class="line"></view>
          <view class="home flex-box flex-ver" @tap="goHome">
            <uni-icons class="imageClass" :size="iconSize" type="home" :color="iconColor"></uni-icons>
          </view>
        </view>
        <!-- 只显示返回icon -->
        <view v-else-if="isGoBack || pages > 1" class="flex-box flex-ver-v" @click.stop="goBack">
          <uni-icons class="imageClass" :size="iconSize" type="left" :color="iconColor"></uni-icons>
        </view>
        <!-- 只显示返回首页icon -->
        <view v-else-if="backMain" class="flex-box flex-ver-v" @click.stop="goHome">
          <uni-icons class="imageClass" :size="iconSize" type="home" :color="iconColor"></uni-icons>
        </view>
        <!-- 自定义插槽 -->
        <view v-else class="flex-box flex-ver-v">
          <slot name="left" />
        </view>
      </view>
      <view class="nav-title" v-if="titleText">
        <view :style="textStyle">{{ titleText }}</view>
      </view>
      <view class="center" v-else>
        <slot name="center" />
      </view>
    </view>
    <slot />
  </view>
</template>

<script setup lang="ts">
interface Search {
  backgroundColor?: string; // 导航栏背景颜色--可以是渐变
  navCustomHeight?: number; // 自定义导航栏高度
  color?: string; // 导航栏文字颜色
  fontSize?: number; // 导航栏文字大小
  iconSize?: number; // 导航栏图标大小
  iconColor?: string; // 导航栏图标颜色
  titleText?: string; // 导航栏标题
  backMain?: boolean; // 是否显示返回首页图标
  isGoBack?: boolean; // 是否显示返回图标
  isGoBackEvent?: boolean; // 是否自定义写返回事件
  goBackUrl?: string; // 返回的url
  urlParam?: string; // 返回的url参数
}
const props = withDefaults(defineProps<Search>(), {
  backgroundColor: "#355db4",
  color: "#fff",
  fontSize: 32,
  iconSize: 18,
  iconColor: "#fff",
  navCustomHeight: 0,
  titleText: "",
  backMain: false,
  isGoBack: false,
  isGoBackEvent: false,
  goBackUrl: "",
  urlParam: ""
});
onLoad(() => {
  setNavSize();
  setStyle();
});
onPageScroll((e: any) => {
  // e.scrollTop 表示当前页面滚动的距离
  console.log(e);
  // 在这里编写你的滚动相关逻辑
});
//状态栏高度
const status = ref(0);
//nav高度
const navHeight = ref(0);
//导航栏高度
const allnavHeight = ref("");
//字体样式
const textStyle = ref("");
// 页面栈的数量
const pages = ref(getCurrentPages().length);
//获取状态栏高度
const setNavSize = () => {
  const app = uni.getSystemInfoSync();
  const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
  let statusBarHeight = app.statusBarHeight || 0;
  status.value = statusBarHeight / (uni.upx2px(100) / 100);
  navHeight.value = menuButtonInfo.height / (uni.upx2px(100) / 100) + 30;
  allnavHeight.value = status.value + navHeight.value + "rpx;";
};
const emits = defineEmits(["goBack"]);
const navStyle = computed(() => ({
  height: props.navCustomHeight ? `${props.navCustomHeight}rpx` : allnavHeight.value,
  background: props.backgroundColor
}));
const statusBarStyle = computed(() => `height:${status.value}rpx;`);
const navBarStyle = computed(() => `height:${navHeight.value}rpx;max-height:${navHeight.value}rpx;`);
//样式设置
const setStyle = () => {
  textStyle.value = ["color:" + props.color, "font-size:" + props.fontSize + "rpx"].join(";");
};
// 返回上一步
const goBack = () => {
  console.log("goBackUrl", pages.value);
  if (props.goBackUrl != "") {
    uni.redirectTo({
      url: `${props.goBackUrl}?${props.urlParam}`
    });
  } else {
    if (!props.isGoBackEvent && pages.value > 1) {
      uni.navigateBack();
    } else {
      emits("goBack");
    }
  }
};
// 返回首页
const goHome = () => {
  uni.reLaunch({
    url: "/pages/tabbarPage/tabbarPage"
  });
};
</script>

<style lang="scss">
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  width: 100%;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: top;
  .navBar {
    position: relative;
    display: flex;
    align-items: center;
    .nav_bar_left {
      height: inherit;
      position: absolute;
      width: 75px;
      display: flex;
      align-items: center;
      margin-left: 10px;
      .back-home {
        display: flex;
        align-items: center;
        width: 100%;
        background: rgba(255, 255, 255, 0.6);
        border-radius: 16px;
        box-sizing: border-box;
        box-shadow: 0 0 1px rgb(207, 207, 207);
        overflow: hidden;
        .back {
          flex: 1;
        }
        .home {
          flex: 1;
        }
        .line {
          width: 1px;
          height: 20px;
          background: rgba(0, 0, 0, 0.2);
          transform: scaleX(0.5);
        }
      }
      .back-icon {
        display: flex;
        align-items: center;
        width: 32rpx;
        height: 100%;
        margin-left: 20rpx;
        .imageClass {
          display: flex;
          justify-content: center;
          align-items: center;
        }
      }
    }

    .nav-title {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    .center {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  }
  .flex-box {
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;
  }
  .flex-ver {
    align-items: center;
    justify-content: center;
  }
  .flex-ver-v {
    align-items: center;
  }
}
</style>


相关文章

基于ElementUi再次封装基础组件文档


Vue3+Vite+Ts+Pinia+Qiankun后台管理系统


vue3+ts基于Element-plus再次封装基础组件文档