| <template> | 
|   <view | 
|     class="tn-custom-nav-bar-class tn-custom-nav-bar" | 
|     :style="[navBarStyle]" | 
|   > | 
|       <view | 
|       class="tn-custom-nav-bar__bar" | 
|       :class="[barClass]" | 
|       :style="[barStyle]" | 
|     > | 
|       <view v-if="isBack"> | 
|         <view v-if="customBack"> | 
|           <view  | 
|             :style="{ | 
|               width: customBackStyleInfo.width + 'px', | 
|               height: customBackStyleInfo.height + 'px', | 
|               marginLeft: customBackStyleInfo.left + 'px' | 
|             }" | 
|           > | 
|             <slot name="back"></slot> | 
|           </view> | 
|         </view> | 
|         <view v-else class="tn-custom-nav-bar__bar__action" @tap="handlerBack"> | 
|             <text class="tn-custom-nav-bar__bar__action--nav-back" :class="[`tn-icon-${backIcon}`]"></text> | 
|             <text class="tn-custom-nav-bar__bar__action--nav-back-text" v-if="backTitle">{{ backTitle }}</text> | 
|         </view> | 
|       </view> | 
|           <view class="tn-custom-nav-bar__bar__content" :style="[contentStyle]"> | 
|               <slot></slot> | 
|           </view> | 
|           <view> | 
|         <slot name="right"></slot> | 
|       </view> | 
|       </view> | 
|   </view> | 
| </template> | 
|   | 
| <script> | 
|   import componentsColorMixin from '../../libs/mixin/components_color.js' | 
|   export default { | 
|     name: 'tn-nav-bar', | 
|     mixins: [componentsColorMixin], | 
|     props: { | 
|       // 层级 | 
|       zIndex: { | 
|         type: Number, | 
|         default: 0 | 
|       }, | 
|       // 导航栏的高度 | 
|       height: { | 
|         type: Number, | 
|         default: 0 | 
|       }, | 
|       // 高度单位 | 
|       unit: { | 
|         type: String, | 
|         default: 'px' | 
|       }, | 
|       // 是否显示返回按钮 | 
|       isBack: { | 
|         type: Boolean, | 
|         default: true | 
|       }, | 
|       // 返回按钮的图标 | 
|       backIcon: { | 
|         type: String, | 
|         default: 'left' | 
|       }, | 
|       // 返回按钮旁显示的文字 | 
|       backTitle: { | 
|         type: String, | 
|         default: '返回' | 
|       }, | 
|       // 透明状态栏 | 
|       alpha: { | 
|         type: Boolean, | 
|         default: false | 
|       }, | 
|       // 是否固定在顶部 | 
|       fixed: { | 
|         type: Boolean, | 
|         default: true | 
|       }, | 
|       // 是否显示底部阴影 | 
|       bottomShadow: { | 
|         type: Boolean, | 
|         default: true | 
|       }, | 
|       // 是否自定义返回按钮 | 
|       customBack: { | 
|         type: Boolean, | 
|         default: false | 
|       }, | 
|       // 返回前回调 | 
|       beforeBack: { | 
|         type: Function, | 
|         default: null | 
|       } | 
|     }, | 
|     computed: { | 
|       navBarStyle() { | 
|         let style = {} | 
|         style.height = this.height === 0 ? this.customBarHeight + this.unit : this.height + this.unit | 
|         if (this.fixed) { | 
|           style.position = 'fixed' | 
|         } | 
|         style.zIndex = this.elZIndex | 
|          | 
|         return style | 
|       }, | 
|       barClass() { | 
|         let clazz = '' | 
|         if (this.backgroundColorClass) { | 
|           clazz += ` ${this.backgroundColorClass}` | 
|         } | 
|         if (this.fontColorClass) { | 
|           clazz += `${this.fontColorClass}` | 
|         } | 
|         if (this.fixed) { | 
|           clazz += ' tn-custom-nav-bar__bar--fixed' | 
|         } | 
|         if (this.alpha) { | 
|           clazz += ' tn-custom-nav-bar__bar--alpha' | 
|         } | 
|         if (this.bottomShadow) { | 
|           clazz += ' tn-custom-nav-bar__bar--bottom-shadow' | 
|         } | 
|          | 
|         return clazz | 
|       }, | 
|       barStyle() { | 
|         let style = {} | 
|         style.height = this.height === 0 ? this.customBarHeight + this.unit : this.height + this.unit | 
|          | 
|         if (this.fixed) { | 
|           style.paddingTop = this.statusBarHeight + 'px' | 
|         } | 
|          | 
|         if(!this.backgroundColorClass) { | 
|           style.backgroundColor = this.backgroundColor !== '' ? this.backgroundColor : '#FFFFFF' | 
|         } | 
|         if (!this.fontColorClass && this.fontColor) { | 
|           style.color= this.fontColor | 
|         } | 
|          | 
|         style.zIndex = this.elZIndex | 
|          | 
|         return style | 
|       }, | 
|       contentStyle() { | 
|         let style = {} | 
|         style.top = this.fixed ? this.statusBarHeight + 'px' : '0px' | 
|         style.height = this.height === 0 ? (this.customBarHeight - this.statusBarHeight) + this.unit : this.height + this.unit | 
|         style.lineHeight = style.height | 
|          | 
|         if (this.isBack) { | 
|           if (this.customBack) { | 
|             const width = (this.customBackStyleInfo.width + this.customBackStyleInfo.left) * 2 | 
|             style.width = `calc(100% - ${width}px)` | 
|           } else { | 
|             style.width = 'calc(100% - 340rpx)' | 
|           } | 
|         } else { | 
|           style.width = '100%' | 
|         } | 
|          | 
|         return style | 
|       }, | 
|       elZIndex() { | 
|         return this.zIndex ? this.zIndex : this.$t.zIndex.navbar | 
|       } | 
|     }, | 
|     data() { | 
|       return { | 
|         // 状态栏的高度 | 
|         statusBarHeight: 0, | 
|         // 自定义导航栏的高度 | 
|         customBarHeight: 0, | 
|         // 自定义返回按钮时,返回容器的宽高边距信息 | 
|         customBackStyleInfo: { | 
|           width: 86, | 
|           height: 32, | 
|           left: 15 | 
|         } | 
|       } | 
|     }, | 
|     mounted() { | 
|       // 获取vuex中的自定义顶栏的高度 | 
|       this.updateNavBarInfo() | 
|     }, | 
|     created() { | 
|       // 获取胶囊信息 | 
|       // #ifdef MP-WEIXIN | 
|       let custom = wx.getMenuButtonBoundingClientRect() | 
|       this.customBackStyleInfo.width = custom.width | 
|       this.customBackStyleInfo.height = custom.height | 
|       this.customBackStyleInfo.left = uni.upx2px(750) - custom.right | 
|       // #endif | 
|     }, | 
|     methods: { | 
|       // 更新导航栏的高度 | 
|       async updateNavBarInfo() { | 
|         // 获取vuex中的自定义顶栏的高度 | 
|         let customBarHeight = this.vuex_custom_bar_height | 
|         let statusBarHeight = this.vuex_status_bar_height | 
|         // 如果获取失败则重新获取 | 
|         if (!customBarHeight) { | 
|           try { | 
|             const navBarInfo = await this.$t.updateCustomBar() | 
|             customBarHeight = navBarInfo.customBarHeight | 
|             statusBarHeight = navBarInfo.statusBarHeight | 
|           } catch(e) { | 
|             setTimeout(() => { | 
|               this.updateNavBarInfo() | 
|             }, 10) | 
|             return | 
|           } | 
|         } | 
|          | 
|         // 更新vuex中的导航栏信息 | 
|         this && this.$t.vuex('vuex_status_bar_height', statusBarHeight) | 
|         this && this.$t.vuex('vuex_custom_bar_height', customBarHeight) | 
|          | 
|         this.customBarHeight = customBarHeight | 
|         this.statusBarHeight = statusBarHeight | 
|       }, | 
|       // 处理返回事件 | 
|       async handlerBack() { | 
|         if (this.beforeBack && typeof(this.beforeBack) === 'function') { | 
|           // 执行回调,同时传入索引当作参数 | 
|           // 在微信,支付宝等环境(H5正常),会导致父组件定义的函数体中的this变成子组件的this | 
|           // 通过bind()方法,绑定父组件的this,让this的this为父组件的上下文 | 
|           let beforeBack = this.beforeBack.bind(this.$t.$parent.call(this))() | 
|           // 判断是否返回了Promise | 
|           if (!!beforeBack && typeof beforeBack.then === 'function') { | 
|             await beforeBack.then(res => { | 
|               // Promise返回成功 | 
|               this.navBack() | 
|             }).catch(err => {}) | 
|           } else if (beforeBack === true) { | 
|             this.navBack() | 
|           } | 
|         } else { | 
|           this.navBack() | 
|         } | 
|       }, | 
|       // 返回上一页 | 
|       navBack() { | 
|          | 
|         // 通过判断当前页面的页面栈信息,是否有上一页进行返回,如果没有则跳转到首页 | 
|         const pages = getCurrentPages() | 
|         if (pages && pages.length > 0) { | 
|           const firstPage = pages[0] | 
|           if (pages.length == 1 && (!firstPage.route || firstPage.route != 'pages/index/index')) { | 
|             uni.reLaunch({ | 
|               url: '/pages/index/index' | 
|             }) | 
|           } else { | 
|             uni.navigateBack({ | 
|               delta: 1 | 
|             }) | 
|           } | 
|         } else { | 
|           uni.reLaunch({ | 
|             url: '/pages/index/index' | 
|           }) | 
|         } | 
|       } | 
|     } | 
|   } | 
| </script> | 
|   | 
| <style lang="scss" scoped> | 
|    | 
|   .tn-custom-nav-bar { | 
|     display: block; | 
|     position: relative; | 
|      | 
|     &__bar { | 
|       display: flex; | 
|       position: relative; | 
|       align-items: center; | 
|       min-height: 100rpx; | 
|       justify-content: space-between; | 
|       min-height: 0px; | 
|       /* #ifdef MP-WEIXIN */ | 
|       padding-right: 220rpx; | 
|       /* #endif */ | 
|       /* #ifdef MP-ALIPAY */ | 
|       padding-right: 150rpx; | 
|       /* #endif */ | 
|       box-shadow: 0rpx 0rpx 0rpx; | 
|       z-index: 9999; | 
|        | 
|       &--fixed { | 
|         position: fixed; | 
|         width: 100%; | 
|         top: 0; | 
|       } | 
|        | 
|       &--alpha { | 
|         background: transparent !important; | 
|         box-shadow: none !important; | 
|       } | 
|        | 
|       &--bottom-shadow { | 
|         box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.05); | 
|       } | 
|        | 
|       &__action { | 
|         display: flex; | 
|         align-items: center; | 
|         height: 100%; | 
|         justify-content: center; | 
|         max-width: 100%; | 
|          | 
|         &--nav-back { | 
|           /* position: absolute; */ | 
|           /* top: 50%; */ | 
|           /* left: 20rpx; */ | 
|           /* margin-top: -15rpx; */ | 
|           // width: 25rpx; | 
|           // height: 25rpx; | 
|           padding: 20rpx; | 
|           font-size: 38rpx; | 
|           line-height: 100%; | 
|           // border-width: 0 0 4rpx 4rpx; | 
|           // border-color: #000000; | 
|           // border-style: solid; | 
|           // transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); | 
|         } | 
|          | 
|         &--nav-back-text { | 
|           padding: 20rpx 20rpx 20rpx 0rpx; | 
|         } | 
|       } | 
|        | 
|       &__content { | 
|         position: absolute; | 
|         text-align: center; | 
|         left: 0; | 
|         right: 0; | 
|         bottom: 0; | 
|         margin: auto; | 
|         font-size: 32rpx; | 
|         cursor: none; | 
|         // pointer-events: none; | 
|         text-overflow: ellipsis; | 
|         white-space: nowrap; | 
|         overflow: hidden; | 
|       } | 
|     } | 
|   } | 
|    | 
| </style> |