• vue3+ts+uniapp实现小程序端input获取焦点计算上推页面距离


    vue3+ts+uniapp实现小程序端input获取焦点计算上推页面距离


    自我记录

    1.先说我这边的需求

    需求

    1.给键盘同级添加一个按钮例如’下一步’ or ‘确认’ 这种按钮
    2.初步想法就是获取input焦点时拿到键盘高度,并给页面的按钮设置fixed,并且bottom为键盘的高度正常逻辑是没问题的!
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    2.发现问题

    发现问题:

    1.当页面input在底部时(可以理解为键盘弹出时的高度会覆盖掉页面底部的input时)因为input有自动上推的属性adjustPosition,此时整个页面就会被上推至显示当前的input位置,重点是整个页面!!!
    2/因为我们的按钮是根据页面去定位的,当整个页面被上推,即使按钮定位的bottom为键盘的高度也会导致按钮没有和键盘贴在一起

    3.解决思路

    1.查看文档是否有能获取到上推距离的属性or方法 ×
    2.通过ref去获取input的target相关 ×
    3.通过uni.createSelectorQuery() 获取input的target相关
    3.1获取到input的底边距离屏幕顶部的距离 - 键盘高度的定位按钮的底边距离屏幕顶部的距离 = 上推距离

    直接上代码

    4.代码展示

    <script setup lang="ts">
    import { getCurrentInstance, ref } from 'vue'
    //  监听键盘高度变化
    const keyboardHeight = ref(0)
    // 当前键盘类型
    const keyboardType = ref('')
    // 下一步
    const nextText = ref('下一步')
    const isNext = ref(false)
    
    const onInputFocus = (event: UniHelper.InputOnFocusEvent, type: string) => {
      // 获取键盘高度
      keyboardHeight.value = Math.ceil(event.detail.height || 0)
      keyboardType.value = type
    
      if (['wage', 'fund', 'socialSecurity'].includes(type)) {
        nextText.value = '确定'
      } else {
        nextText.value = '下一步'
      }
      handleKeyboardOpen(type)
      // 监听键盘高度发生变化时(来短信验证码)提高按钮
      uni.onKeyboardHeightChange((res) => {
        keyboardHeight.value = Math.ceil(res.height)
        handleKeyboardOpen(type)
      })
    }
    
    // 失去焦点触发
    const onInputBlur: UniHelper.InputOnBlur = () => {
      if (isNext.value) return (isNext.value = false)
       // 移除监听事件
      uni.offKeyboardHeightChange()
      keyboardHeight.value = 0
      keyboardType.value = ''
    }
    // 下一步触发
    const onNextConfirm = (event: UniHelper.CustomEvent, type: string) => {
      isNext.value = true
      event.stopPropagation()
      if (type === 'name') {
        idCardInput.value = true
      } else if (type === 'idCard') {
        phoneInput.value = true
      } else if (['phone', 'wage', 'fund', 'socialSecurity'].includes(type)) {
        idCardInput.value = false
        phoneInput.value = false
        nameInput.value = false
        isNext.value = false
      }
    }
    // 主要逻辑相关!!!
    //1、首先导入当前组件的实例 form 'vue'
    var currentInstance = getCurrentInstance()
    // 键盘弹出时计算推上去的距离
    const handleKeyboardOpen = (type: string) => {
      // 使用 inputQuery 获取输入框 & 按钮位置
      //2、添加上in方法
      const inputQuery = uni.createSelectorQuery().in(currentInstance)
      const ButtonQuery = uni.createSelectorQuery().in(currentInstance)
      let rectBottom = 0
      let rectBottom2 = 0
      // 获取输入框
      inputQuery
        .select(`#${type}`)
        .boundingClientRect((rect: any) => {
          console.log(rect, 'rect')
          rectBottom = rect.bottom
        })
        .exec()
      // 获取按钮位置
      setTimeout(() => {
        ButtonQuery.select(`#next`)
          .boundingClientRect((rect: any) => {
            // rect 包含了按钮的位置信息
            rectBottom2 = rectBottom - rect.bottom
            // >0 证明 上推页面了 !=0 证明获取到按钮信息了
            if (rectBottom2 > 0 && rect.bottom !== 0) {
              keyboardHeight.value = keyboardHeight.value - rectBottom2
            }
          })
          .exec()
      })
    }
    </script>
    <template>
     <input
      id="fund"
      class="input"
      focus
      type="digit"
      placeholder="请输入"
      placeholder-style="font-size:28rpx"
      v-model="formInfo.fundVal"
      @focus="onInputFocus($event, 'fund')"
      @blur="onInputBlur"
    />
    
    <input
    id="socialSecurity"
    class="input"
    type="digit"
    focus
    placeholder="请输入"
    placeholder-style="font-size:28rpx"
    v-model="formInfo.socialSecurityVal"
    @focus="onInputFocus($event, 'socialSecurity')"
    @blur="onInputBlur"
    />
    
    <input
     id="wage"
      class="input"
      type="digit"
      placeholder="请输入签约工资"
      v-model="formBottomInfo.wage"
      @focus="onInputFocus($event, 'wage')"
      @blur="onInputBlur"
    />
     <!-- 下一步 -->
     <view
       id="next"
       class="nextKey"
       :style="{ bottom: keyboardHeight + 'px', display: keyboardHeight ? 'block' : 'none' }"
       @tap.stop="onNextConfirm($event, keyboardType)"
       >{{ nextText }}</view
     >
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    整理不易,如有转载请备注原文地址!

  • 相关阅读:
    分布式 PostgreSQL 集群(Citus)官方示例 - 多租户应用程序实战
    Guava的反射工具
    计算机复试面试题总结
    为 VitePress 网站添加 RSS 订阅支持
    python:使用随机森林回归模型进行数据预测
    C++ STL迭代器失效问题
    Boot Rom和Bootloader
    Python数据库编程全指南SQLite和MySQL实践
    GCC + Vscode 搭建 nRF52xxx 开发环境
    基于ssm的潮牌运动服饰数码商城管理系统(idea+spring+springmvc+mybatis+jsp)
  • 原文地址:https://blog.csdn.net/zhgweb/article/details/132669316