uniapp自定义小程序头部导航栏,navigationbar,封装成公共组件带返回按钮和标题,带图片logo,实现导航栏下方滚动,。(组件代码在最下方)以下是组件的完整代码。

logo图片(无点击效果)
在这里插入图片描述
带返回按钮和标题(需要加backFn,返回上一页事件)
在这里插入图片描述
如何使用:(组件代码在最下方)

  1. 引用
import NavBar from "../../components/navBar/navBar.vue";
  1. 注册
 components: {
   NavBar,
 },
  1. 使用
    .lxy-nav-bar可设置导航栏背景图或颜色
    (1)logo
 <navBar>
      <div slot="left" class="left_box">
      //直接添加所需图片
        <image class="logo" src="../../static/logo.png"></image>
      </div>
  </navBar>

(2)带返回按钮和标题

 <navBar>
      <view slot="left" @click="backFn" class="left_box">
            //返回<箭头的图片,也可以用伪元素,iconfont
        <image src="../../static/back-icon.png"></image>
        <text> 浏览历史 </text>
      </view>
  </navBar>
  //返回上一级事件
  backFn(){
  	 uni.navigateBack();
  }

<------------------------------>(如要实现导航栏下方滚动)

<template>
  <div class="intro_page">
	 <navBar>
      <view slot="left" @click="backFn" class="left_box">
      //返回<箭头的图片,也可以用伪元素,iconfont
        <image src="../../static/back-icon.png"></image>
        <text> 浏览历史 </text>
      </view>
  	</navBar>
    <scroll-view
      scroll-y
      :style="'height:calc( 100vh - ' + barHeight + 'px)'"
      class="countHeight"
    >
    //barHeight需要获取
    可滚动区域
	</scroll-view>
  </div>
</template>
<script>
import navBar from "../../components/navBar/navBar.vue";

export default {
  components: { navBar },
  data() {
    return {
      barHeight: 0,
    };
  },
  
  methods: {
    backFn() {
      uni.navigateBack();
    },
  },
  mounted() {
  //组件里会自动把当前导航栏的高度存放到globalData,我们只需要获取使用即可
    let obj = getApp().globalData;
    this.barHeight = obj.Allheight;
  },
};
</script>
<style>
//如自定义导航栏页面多,可在app.vue使用全局样式
.countHeight {
  overflow-y: auto;
}
</style>

以下是组件的完整代码

<template>
  <view class="lxy-nav-bar" :style="' height: ' + Allheight + 'px; '">
    <view
      :class="
        ios
          ? ' lxy-nav-bar__placeholder ios'
          : 'lxy-nav-bar__placeholder android'
      "
      :style="' padding-top:' + Allheight + 'px; visibility: hidden;'"
    ></view>
    <view
      :class="ios ? ' lxy-nav-bar__inner ios' : ' lxy-nav-bar__inner android'"
      :style="navigationbarinnerStyle"
    >
      <view class="lxy-nav-bar__left" :style="navBarLeft">
        <slot name="left"></slot>
      </view>
      <view class="lxy-nav-bar__center">
        <block v-if="title">
          <text class="lxy-nav-bar__center-title"> {{ title }} </text>
        </block>
        <view
          class="lxy-nav-bar-search"
          :style="'height:' + capsulePosition.height + 'px;'"
          v-else-if="searchBar"
          @click="search"
        >
          <view class="lxy-nav-bar-search__icon" />
          <view class="lxy-nav-bar-search__input"> {{ searchText }} </view>
        </view>
        <!-- 暂时不开发标题loading. 看后期需要 -->
        <!-- <view v-if="{{loading}}" class="lxy-nav-bar__loading">
                <view class="lxy-loading" style="width:{{size.width}}px;height:{{size.height}}px;"></view>
            </view> -->
        <block v-else>
          <slot name="center"></slot>
        </block>
      </view>
      <block class="lxy-nav-bar__right">
        <slot name="right"></slot>
      </block>
    </view>
  </view>
</template>
<script>
export default {
  props: {
    extClass: {
      type: String,
      value: "",
    },
    background: {
      type: String,
      value: "rgba(255, 255, 255, 1)",
      observer: "_showChange",
    },
    backgroundColorTop: {
      type: String,
      value: "rgba(255, 255, 255, 1)",
      observer: "_showChangeBackgroundColorTop",
    },
    color: {
      type: String,
      value: "rgba(0, 0, 0, 1)",
    },
    title: {
      type: String,
      value: "",
    },
    searchText: {
      type: String,
      value: "点我搜索",
    },
    searchBar: {
      type: Boolean,
      value: false,
    },
    back: {
      type: Boolean,
      value: false,
    },
    home: {
      type: Boolean,
      value: false,
    },
    iconTheme: {
      type: String,
      value: "black",
    },
    delta: {
      type: Number,
      value: 1,
    },
  },
  data() {
    return {
      options: {
        multipleSlots: true,
        addGlobalClass: true,
      },
      navBarLeft: null,
      navigationbarinnerStyle: "",
      statusBarHeight: null,
      navBarHeight: null,
      capsulePosition: null,
      navBarExtendHeight: null,
      ios: null,
      windowWidth: null,
      Allheight: null,
    };
  },

  created() {
    this.getSystemInfo();
    this.setStyle();
    if (!this.ios) {
      this.setStyle();
    }
  },
  attached() {
    this.setStyle(); //设置样式
  },
  methods: {
    setStyle(life) {
      const {
        statusBarHeight,
        navBarHeight,
        capsulePosition,
        navBarExtendHeight,
        ios,
        windowWidth,
      } = getApp().globalData;

      const { back, home, title } = this;
      let rightDistance = windowWidth - capsulePosition.right; //胶囊按钮右侧到屏幕右侧的边距
      let leftWidth = windowWidth - capsulePosition.left; //胶囊按钮左侧到屏幕右侧的边距

      let navigationbarinnerStyle = [
        `color: ${this.color}`,
        `background: ${this.background}`,
        `height:${navBarHeight + navBarExtendHeight}px`,
        `padding-top:${statusBarHeight}px`,
        `padding-right:${leftWidth}px`,
        `padding-bottom:${navBarExtendHeight}px`,
      ].join(";");
      let navBarLeft = [`width:auto`, `margin-left:0px`].join(";");

      this.navigationbarinnerStyle = navigationbarinnerStyle;
      this.navBarLeft = navBarLeft;
      this.navBarHeight = navBarHeight;
      this.capsulePosition = capsulePosition;
      this.navBarExtendHeight = navBarExtendHeight;
      this.ios = ios;
      this.Allheight = navBarHeight + navBarExtendHeight;
    },
    getSystemInfo() {
      var app = getApp();
      if (app.globalSystemInfo && !app.globalSystemInfo.ios) {
        return app.globalSystemInfo;
      } else {
        let systemInfo = uni.getSystemInfoSync();
        let ios = !!(systemInfo.system.toLowerCase().search("ios") + 1);
        let rect;
        try {
          rect = uni.getMenuButtonBoundingClientRect
            ? uni.getMenuButtonBoundingClientRect()
            : null;
          if (rect === null) {
            throw "getMenuButtonBoundingClientRect error";
          }
          //取值为0的情况  有可能width不为0 top为0的情况
          if (!rect.width || !rect.top || !rect.left || !rect.height) {
            throw "getMenuButtonBoundingClientRect error";
          }
        } catch (error) {
          let gap = ""; //胶囊按钮上下间距 使导航内容居中
          let width = 96; //胶囊的宽度
          if (systemInfo.platform === "android") {
            gap = 8;
            width = 96;
          } else if (systemInfo.platform === "devtools") {
            if (ios) {
              gap = 5.5; //开发工具中ios手机
            } else {
              gap = 7.5; //开发工具中android和其他手机
            }
          } else {
            gap = 4;
            width = 88;
          }
          if (!systemInfo.statusBarHeight) {
            //开启wifi的情况下修复statusBarHeight值获取不到
            systemInfo.statusBarHeight =
              systemInfo.screenHeight - systemInfo.windowHeight - 20;
          }
          rect = {
            //获取不到胶囊信息就自定义重置一个
            bottom: systemInfo.statusBarHeight + gap + 32,
            height: 32,
            left: systemInfo.windowWidth - width - 10,
            right: systemInfo.windowWidth - 10,
            top: systemInfo.statusBarHeight + gap,
            width: width,
          };
          console.log("error", error);
        }

        let navBarHeight = "";
        if (!systemInfo.statusBarHeight) {
          systemInfo.statusBarHeight =
            systemInfo.screenHeight - systemInfo.windowHeight - 20;
          navBarHeight = (function () {
            let gap = rect.top - systemInfo.statusBarHeight;
            return 2 * gap + rect.height;
          })();
          systemInfo.statusBarHeight = 0;
          systemInfo.navBarExtendHeight = 0; //下方扩展4像素高度 防止下方边距太小
        } else {
          navBarHeight = (function () {
            let gap = rect.top - systemInfo.statusBarHeight;
            return systemInfo.statusBarHeight + 2 * gap + rect.height;
          })();
          if (ios) {
            systemInfo.navBarExtendHeight = 4; //下方扩展4像素高度 防止下方边距太小
          } else {
            systemInfo.navBarExtendHeight = 0;
          }
        }
        systemInfo.navBarHeight = navBarHeight; //导航栏高度不包括statusBarHeight
        systemInfo.capsulePosition = rect; //右上角胶囊按钮信息bottom: 58 height: 32 left: 317 right: 404 top: 26 width: 87 目前发现在大多机型都是固定值 为防止不一样所以会使用动态值来计算nav元素大小
        systemInfo.ios = ios; //是否ios
        systemInfo.Allheight =
          systemInfo.navBarHeight + systemInfo.navBarExtendHeight;

        app.globalData = systemInfo; //将信息保存到全局变量中,后边再用就不用重新异步获取了
        return systemInfo;
      }
    },
    _showChange: function (value) {
      this.setStyle();
    },
    // 返回事件
    backFn: function () {
      uni.$emit("back", { delta: this.delta });
    },
  },
};
</script>
<style>
view,
text,
scroll-view,
input,
button,
image,
cover-view {
  box-sizing: border-box;
}

.lxy-nav-bar {
  background-image: url(https://dev2.ctsec.com:10045/static/image/navbarbgc.png);
  background-size: 100% 100%;
  box-sizing: border-box;
  background-repeat: no-repeat;
}
view,
text,
scroll-view,
input,
button,
image,
cover-view {
  box-sizing: border-box;
}
.lxy-nav-bar .ios {
  --height: 44px; /* 4*2+32 */
  --right: 97px; /* 10+87 */
  --navBarExtendHeight: 4px;
  box-sizing: border-box;
}
.lxy-nav-bar .android {
  --height: 48px; /* 8*2+32 */
  --right: 96px; /* 10+87 */
  --navBarExtendHeight: 4px;
  box-sizing: border-box;
}
.lxy-nav-bar .devtools {
  --height: 42px; /* 5*2+32 */
  --right: 88px; /* 10+87 */
  --navBarExtendHeight: 4px;
  box-sizing: border-box;
}
.lxy-nav-bar__inner {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 5001;
  height: var(--height);
  display: flex;
  align-items: center;
  padding-right: var(--right);
  width: 100%;
  padding-bottom: var(--navBarExtendHeight);
}
.lxy-nav-bar__inner .lxy-nav-bar__left {
  position: relative;
  width: var(--right);
  height: 32px;
  /*  padding-left: 10px; */
  display: flex;
  align-items: center;
}
.lxy-nav-bar__buttons {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  border-radius: 16px;
  border: 1rpx solid rgba(204, 204, 204, 0.6);
  position: relative;
}
.lxy-nav-bar__buttons.android {
  border: 1rpx solid rgba(234, 234, 234, 0.6);
}
.lxy-nav-bar__buttons::after {
  position: absolute;
  content: "";
  width: 1rpx;
  height: 18.4px;
  background: rgba(204, 204, 204, 0.6);
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.lxy-nav-bar__buttons.android::after {
  background: rgba(234, 234, 234, 0.6);
}
.lxy-nav-bar__button {
  width: 50%;
  height: 100%;
  display: flex;
  font-size: 12px;
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 1em 2em;
}

.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_goback:active,
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_gohome:active {
  opacity: 0.5;
}
.lxy-nav-bar__inner .lxy-nav-bar__center {
  font-size: 17px;
  line-height: 17px;
  text-align: center;
  position: relative;
  flex: 1;
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 10px;
}
.lxy-nav-bar__inner .lxy-nav-bar__center .lxy-nav-bar__center-title {
  margin-top: -2px;
}
.lxy-nav-bar__inner .lxy-nav-bar__loading {
  font-size: 0;
}
.lxy-nav-bar__inner .lxy-nav-bar__loading .lxy-loading {
  margin-left: 0;
}
.lxy-nav-bar__inner .lxy-nav-bar__right {
  margin-right: 10px;
}
.lxy-nav-bar__placeholder {
  height: var(--height);
  background: #f8f8f8;
  position: relative;
  z-index: 50;
}

.lxy-nav-bar-search {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 32px;
  border-radius: 16px;
  position: relative;
  background: #f6f6f6;
}

.lxy-nav-bar-search__input {
  height: 100%;
  display: flex;
  align-items: center;
  color: #999;
  font-size: 15px;
  line-height: 15px;
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_goback {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E  %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z'/%3E%3C/svg%3E");
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_goback.white {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E  %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z' fill='%23ffffff'/%3E%3C/svg%3E");
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_gohome {
  background-image: url("data:image/svg+xml,%3Csvg t='1565752242401' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='4326' width='48' height='48'%3E%3Cpath d='M931.148 451.25L591.505 97.654c-21.106-21.953-49.313-34.034-79.551-34.034-30.235 0-58.448 12.081-79.554 34.034L92.76 451.25c-35.049 36.498-30.536 68.044-24.742 81.222 4.13 9.35 18.07 35.05 58.231 35.05h49.78v272.016c0 61.756 44.342 119.906 107.357 119.906h144.587v-287.87c0-30.866-4.675-48.062 26.848-48.062h114.268c31.52 0 26.845 17.196 26.845 48.061v287.872h144.588c63.013 0 107.358-58.15 107.358-119.906V567.523h49.782c40.16 0 54.1-25.7 58.229-35.05 5.793-13.18 10.306-44.726-24.743-81.224z m-33.486 60.28h-105.77v328.007c0 30.865-19.877 63.917-51.37 63.917h-88.6V671.572c0-61.761-19.79-104.05-82.832-104.05H454.821c-63.045 0-82.836 42.289-82.836 104.05v231.883h-88.599c-31.495 0-51.37-33.052-51.37-63.917V511.529H126.25c-0.984 0-1.888-3.852-2.708-3.907 1.94-3.388 5.276-11.975 10.825-17.743l339.671-353.35c10.142-10.578 24.467-17.057 38.353-16.924 13.888-0.133 27.342 6.346 37.483 16.923L889.54 489.88c5.549 5.768 8.885 14.355 10.825 17.743-0.818 0.055-1.72 3.907-2.704 3.907z' fill='%23000000' p-id='4327'%3E%3C/path%3E%3C/svg%3E");
  background-size: 22px 22px;
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_gohome.white {
  background-image: url("data:image/svg+xml,%3Csvg t='1565752242401' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='4326' width='48' height='48'%3E%3Cpath d='M931.148 451.25L591.505 97.654c-21.106-21.953-49.313-34.034-79.551-34.034-30.235 0-58.448 12.081-79.554 34.034L92.76 451.25c-35.049 36.498-30.536 68.044-24.742 81.222 4.13 9.35 18.07 35.05 58.231 35.05h49.78v272.016c0 61.756 44.342 119.906 107.357 119.906h144.587v-287.87c0-30.866-4.675-48.062 26.848-48.062h114.268c31.52 0 26.845 17.196 26.845 48.061v287.872h144.588c63.013 0 107.358-58.15 107.358-119.906V567.523h49.782c40.16 0 54.1-25.7 58.229-35.05 5.793-13.18 10.306-44.726-24.743-81.224z m-33.486 60.28h-105.77v328.007c0 30.865-19.877 63.917-51.37 63.917h-88.6V671.572c0-61.761-19.79-104.05-82.832-104.05H454.821c-63.045 0-82.836 42.289-82.836 104.05v231.883h-88.599c-31.495 0-51.37-33.052-51.37-63.917V511.529H126.25c-0.984 0-1.888-3.852-2.708-3.907 1.94-3.388 5.276-11.975 10.825-17.743l339.671-353.35c10.142-10.578 24.467-17.057 38.353-16.924 13.888-0.133 27.342 6.346 37.483 16.923L889.54 489.88c5.549 5.768 8.885 14.355 10.825 17.743-0.818 0.055-1.72 3.907-2.704 3.907z' fill='%23ffffff' p-id='4327'%3E%3C/path%3E%3C/svg%3E");
  background-size: 22px 22px;
}
.lxy-nav-bar-search__icon {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-image: url("data:image/svg+xml,%3Csvg t='1565691512239' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='1240' width='48' height='48'%3E%3Cpath d='M819.2 798.254545L674.909091 653.963636c46.545455-48.872727 74.472727-114.036364 74.472727-186.181818 0-151.272727-123.345455-274.618182-274.618182-274.618182-151.272727 0-274.618182 123.345455-274.618181 274.618182 0 151.272727 123.345455 274.618182 274.618181 274.618182 65.163636 0 128-23.272727 174.545455-62.836364l144.290909 144.290909c2.327273 2.327273 6.981818 4.654545 11.636364 4.654546s9.309091-2.327273 11.636363-4.654546c6.981818-6.981818 6.981818-18.618182 2.327273-25.6zM235.054545 467.781818c0-132.654545 107.054545-239.709091 239.709091-239.709091 132.654545 0 239.709091 107.054545 239.709091 239.709091 0 132.654545-107.054545 239.709091-239.709091 239.709091-132.654545 0-239.709091-107.054545-239.709091-239.709091z' fill='%23999999' p-id='1241'%3E%3C/path%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: cover;
}
</style>
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现微信小程序自定义navigationbar顶部导航栏的兼容适配,首先需要明确几个关键点。 1. 自定义导航栏的设计:根据产品需求和界面设计,确定导航栏的样式、背景色、标题按钮等元素。 2. 获取手机屏幕的尺寸:小程序可以使用`wx.getSystemInfoSync()`方法获取手机屏幕的尺寸信息。 3. 设置导航栏高度:根据系统的不同,导航栏的高度也会有所差异。可以把导航栏的高度设置为一个相对较大的值,以适应大部分机型。当实际机型不同导航栏高度时,可以根据不同机型进行适配。 4. 适配不同机型的刘海屏或异形屏:对于刘海屏或者异形屏的机型,需要判断屏幕顶部是否存在刘海等异形部分,并进行相应的适配。可以使用`wx.getMenuButtonBoundingClientRect()`方法来获取右上角胶囊按钮的位置信息,从而确定导航栏背景的偏移和大小。 5. 设置页面的顶部内边距:在有自定义导航栏的情况下,为了避免导航栏遮挡页面内容,需要设置页面的顶部内边距。 6. 适配多端:微信小程序支持在不同的平台上运行,如iOS、Android、小程序开发工具等。因此要确保自定义导航栏在不同平台上的显示效果一致。 综上所述,通过了解手机屏幕尺寸、设置导航栏高度和背景、适配刘海屏、设置页面内边距以及多端适配等步骤,可以实现微信小程序自定义navigationbar顶部导航栏的兼容适配,使其在不同机型上都能够正常显示和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值