解决uni-app 微信小程序,底部弹出popup的时隐藏首页tababr

lxf2023-04-21 19:14:02

最近开发需求微信小程序,被安排了一个需求调整,当在小程序首页进行某些操作从页面底部弹出popup弹窗框时,需要隐藏首页的tabbar。

基本交互描述

点击首页的按钮,从底部弹出popup A弹窗。点击弹窗左边的分享按钮,会关闭当前的的popup A再弹出一个从底部弹出的popup B,新的popup B有两个分享按钮,点击分享关闭当前弹窗。如点击弹窗右边的【按钮】,则是跳转到另一页面,也关闭弹窗。没有展示底部弹出的popup时,tabbar正常展示,若是popup从底部弹出则隐藏tabbar。

解决uni-app 微信小程序,底部弹出popup的时隐藏首页tababr

实现思路与具体实现步骤

开发中使用的UI框架为 uviewui 1.x

基本代码结构
<template>
  <button @click="makePopShow">按钮</button>
  <u-popup v-model="showPopA" mode="bottom" @close="closeFunPop()">
      <view class="u-flex u-row-around">
        <button type="primary" @click="showSharePop">
          <u-icon name="share-fill" size="48"><u-icon>
        </button>
        <button @click="goNext"></button>
      </view>
  </u-popup>
  <u-popup v-model="showPopB" mode="bottom" @close="closeFunPop()">
      <view class="u-flex u-row-around">
        <button type="primary" open-type="share">
          <u-icon name="share-fill" size="48"><u-icon>
        </button>
        <button type="primary" open-type="share">
           <u-icon name="share-fill" size="48"><u-icon>
        </button>
      </view>
  </u-popup>
</template>
<script>
    export default {
    data() {
      return {
        showPopA: false,
        showPopB: false
      }
    },
    methods: {
      hideTabBar() {
	uni.hideTabBar({ animation: true });
      },
      makePopShow() {
        this.hideTabBar();
        setTimeout(() => {
            this.showPopA = true;
        }, 100)
      },
      closeFunPop() {
	console.log('close');
        uni.showTabBar({ animation: true });
        this.showPopA = false;
        this.showPopB = false;
      },
      showSharePop() {
        this.showPopA = false;
        this.hideTabBar();
        setTimeout(() => {
            this.showIviteNextPop = true;
        }, 100)
      },
      goNext() {
        let url = '/pages/next/index'
        uni.navigateTo({
            url,
            success: () => {
                console.log('start')
                uni.showTabBar({ animation: true });
                console.log('end')
            }
        })
      }, 
    }
  }
</script>

场景

点击页面按钮,弹出popup A,此时下一步进行:直接关闭popup A点击popup A内部右边的按钮点击popup A内部左边分享按钮弹出新的popup

  1. 直接关闭popup A

    直接关闭upopp则会触发该组件close方法,此时调用定义的closeFunPop是完全没问题的。

  2. 点击popup A右边的【按钮】

    点击右边的【按钮】,会跳转到新的页面,但是单返回首页会发现tabbar依旧是隐藏的。查看小程序开发者工具的控制台,调用goNext方法时,控制台打印了'start''end',说明uni.showTabBar({ animation: true })执行了;目前无法定位到原因,那么就想其他法子解决问题,毕竟需求有deadline。查看文档,uni-app页面生命周期

    解决uni-app 微信小程序,底部弹出popup的时隐藏首页tababr

在uni-app微信小程序首页的onShow生命周期,调用uni.showTabBar({ animation: true }),这样当我们调用goNext方法,再返回到首页就会正常的展示tabbar。

onShow() {
  uni.showTabBar({ animation: true });
}

体验的时候会发现解决上一个问题又会带来新的问题。问题就是每次进入首页都会执行uni.showTabBar({ animation: true }),导致进入首页就会底部tabbar明显有uni.showTabBar的动画效果,接下来看看如何优化。优化的关键点:“页面的onShow生命周期内,只有当小程序tabbar为隐藏状态,才调用uni.showTabBar({ animation: true }),其他情况不做处理”。

onShow() {
    const systemInfo = uni.getSystemInfoSync();
    const tabBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - systemInfo.statusBarHeight;
    const isTabBarHidden = tabBarHeight <= 0;
    if (isTabBarHidden) {
      uni.showTabBar({ animation: true });
    }
}

通过在首页获取系统信息systemInfo,通过screenHeight - windowHeight - statusBarHeight的差值,判断tabbar是否隐藏。需要注意的是:在我使用微信开发者工具(1.06.2301040 Stable),即使从首页点击Popup A的右边按钮跳转跳转到新的页面,然后返回首页的tabbar为隐藏状态tabBarHeight的值依然大于0。但是我在真机测试下,结果如下:

机型微信版本tabBarHeight的值
三星 SM-G9910 Android 13Version 8.0.32小于0
Iphone 6s IOS 14.6Version 8.0.7小于0

经过真机测试,验证优化onShow生命周期内执行uni.showTabBar({ animation: true })的时机调整大概率是可行的。

  1. 点击popup A左边的分享按钮

流程如下:调用showSharePop,关闭upopp A;隐藏tabbar; 显示关闭upopp B

showSharePop() {
  this.showPopA = false;
  this.hideTabBar();
  setTimeout(() => {
    this.showPopB = true;
  }, 100)
},

写完之后会发现,执行showSharePop方法达不到预想的效果,弹出Popup B的同时也会让小程序首页底部的tabbar显示如下图:

解决uni-app 微信小程序,底部弹出popup的时隐藏首页tababr

这是因为执行showSharePop的时this.showPopA = false会触发popup A的closeFunPop方法,查看上面的closeFunPop方法就会知道在执行该方法的同时会执行uni.showTabBar({ animation: true }),所有需要调整closeFunPop方法。并需要在data中新增一个变量showTarBar: true
调整showSharePopcloseFunPop``makePopShow方法

// popup A 组件的closeFunPop方法也需要同时调整
closeFunPop(showTarBar=true) {
  console.log('close');
  if (showTarBar) {
    uni.showTabBar({ animation: true });
  }
  this.showPopA = false;
  this.showPopB = false;
},
showSharePop() {
  this.showTarBar = false;
  this.showPopA = false;
  this.hideTabBar();
  setTimeout(() => {
    this.showPopB = true;
  }, 100)
},
// 并且在makePopShow执行始终保持 showTarBar: true
 makePopShow() {
  this.hideTabBar();
  this.showTarBar = true;
  setTimeout(() => {
    this.showPopA = true;
  },  100)
},

上述的方法是可以成功的解决,Popup B与tabbar同时出现的bug。但是转念意向,如果不引入showTarBar也能否达到目的呢?那么就成showSharePop方法入手。

showSharePop() {
   // 暂时隐藏这一行
  // this.showTarBar = false;
  this.showPopA = false;
  uni.hideTabBar({
    animation: true,
    success: () => {
      setTimeout(() => {
          this.showPopB = true;
      }, 100)
    }
  })
},

调整了showSharePop方法,调用此方法时会关闭Popup A,并且会触发popup A的closeFunPop方法(过程会显示tabbar,实际不可见),但是此时popup B没有立马展示而是在tabbar隐藏成功之后才会展示。所有并不会复现