popup必须向上移动数值(负数)

lxf2023-04-19 18:46:02

叙述难题

<template>
   <view id="demo">
    <view class="mainContent">
    <!-- 省去正中间内容 -->
    </view>
    <u-popup mode="bottom" :custom-style="popupStyle" height="90%">
      <!--  根据自己的需求提示框只能够在这两个部件直接切换  -->
      <template-list></template-list>
      <edit-template-item
          :scrollTop="scrollTop"
          @moveTop="movePopFixedTop"
  @scroll="makePageScroll"
        >
      </edit-template-item>
    <u-popup>
  </view>
</template>

正常的情况是,实行某种姿势弹出来popup,点一下textarea部件文本框弹出来软件电脑键盘。具体情况实行以上姿势弹出对话框软件电脑键盘遮住了文本框,不能正常在输入文本具体内容。展现如下图所示:

popup必须向上移动数值(负数)

处理问题

popup必须向上移动数值(负数)
解决策略

按不同情况来分析,网页页面有下拉列表及其当前页无下拉列表

  1. 网页页面无下拉列表
    moveTop相当于 100vh - (kbdHeight inputBottomY ),三个系数的计算结果可想而知popup必须向上移动数值(负数)。
    流程步骤:监视文本框focus事情;计算节点inputBottomY数值;edit-template-item部件开启moveTop事情this.$emit('moveTop', { top: moveTop });网页页面特定方式接受moveTop事件传值,从而使popup向上移动 moveTop (px)。
  2. 网页页面有下拉列表

根据上边的无下拉列表版本号,发觉在一屏内就容易解决popup必须向上移动的使用量。那就“变着法儿”再次延用上边的思路。
如何方法呢?
第一步:监视界面的翻转,然后把scrollTop值发送给子组件
第二步:edit-template-item开启一个 scroll事情,让页面滚动到顶端;
第三步:再度测算文本框连接点inputBottomY数值(mounted时测算过一次);
第四步:从而使popup向上移动 moveTop (px);
第五步:文本框失去焦点时,使界面的下拉列表从顶端翻转到以前位置同时使popup恢复正常以前位置;

具体编码

edit-template-item部件

<script>
    export default {
        props: {
            scrollTop: {
                type: Number,
                default: 0
            }
        },
        mounted() {
            this.getPointLoaction();
        },
        data() {
            return {
                    inputBottomY: 0,
                    hasRecord: false
            }
        },
methods: {
            // 获得文本框节点定位信息
            getPointLoaction() {
                this.$nextTick(() => {
                const query = uni.createSelectorQuery().in(this);
                query.select('#iputTextarea').boundingClientRect(data => {
                      this.inputBottomY = data.bottom;
                    }).exec();
                })
            },
            // 文本框聚失去焦点时,下拉列表翻转陈到之前位置,popup挪动到上一位置
            onBlurInput() {
                this.hasRecord = false;
                // 页面滚动到原处
                this.$emit('scroll', { scrollTop: this.oldScrollTop,  });
                this.$nextTick(() => {
                    // popup恢复正常原处
                    this.$emit('moveTop', { top: 0 });
                })
            },
           // 文本框对焦时实施的实际操作
           onFocusInput(event) {
                if (!this.hasRecord) {
                    this.hasRecord = true;
                    // 纪录上一次的翻转scrollTop值,用以文本框失去焦点时页面滚动到原处
                    this.oldScrollTop = this.scrollTop;
                    setTimeout(() => {
                        // 由于连接点部位或许已经更改,再度获得连接点部位
this.getPointLoaction();
                        const kbdHeight = event.detail.height;
if (this.oldScrollTop > 0) {
                            this.$emit('scroll', { scrollTop: 0 });
                            this.$nextTick(() => {
    const query = uni.createSelectorQuery().in(this);    query.select('#iputTextarea').boundingClientRect(data => {
 this.inputBottomY = data.bottom;}).exec();
                            })
}
                        let moveTop = 'calc(100vh - '   Number(kbdHeight   this.inputBottomY)   'rpx'   ')';
this.$emit('moveTop', { top: moveTop });
                    }, 25)
}
            },
}
    }
</script>

当前页

<script>
  export default {
    data() {
      return {
        scrollTop: 0,
      }  
    },
    methods: {
      // 监视页面滚动,然后把值传递给edit-template-item部件
      onPageScroll(e) {
          this.scrollTop = e.scrollTop;
      },
      // 接受edit-template-item触发的scroll事情,使网页页面滑到顶端或者还原到上一次滚动的部位
      makePageScroll(data) {
          uni.pageScrollTo({
              selector: '#addProduct',
              scrollTop: data.scrollTop,
              duration: 15
          });
      },
      movePopFixedTop(data) {
          this.makePageScroll();
          this.$nextTick(() => {
          // 使popup向上移动edit-template-item触发的moveTop事情传送数值moveTop
              this.$set(this.popupStyle, 'top', data.top);
          })
    }
  }
</script>

上边无非就是解决的办法的实际编码小细节。留意上边编码添加一个hasRecord数值,用以纪录是不是点开启过focus事情。早已触动了此次事件在软件电脑键盘并没有收拢并且没有监视到输blur情况时,再度开启focus事情,不用实行一切实际操作。假定没有一个纪录是不是点开启过focus事情数值,则便是每一次点一下文本框(未失去焦点以前),都会使popup移位一个值(每一次挪动数值各不相同,由于inputBottomY都有所不同)。

常见问题

  • 应用 uni.createSelectorQuery() API获得连接点部位有关信息,必须在生命期 mounted 之后进行启用。
  • 最好使用uni-app的textarea部件,监视focus事情获得电脑键盘相对高度。(uni.onKeyBoardHeightChange对于自己我应用 Android版本 13,经常会在电脑键盘早已弹出对话框前提下,没法监视取得成功软件电脑键盘相对高度的改变)
  • textarea部件或者uviewui的input部件不必放置uni-App的scroll-view部件内部结构 ,会导致整个微信小程序都相当卡屏,务必重新进入来解决卡屏难题。(对于自己我应用 Android版本 13 就会非常卡屏,检测朋友所使用的iphone没有明显卡屏状况)