UniApp键盘监听全攻略

UniApp 键盘抬起

概述

在移动端开发中,键盘的弹出和收起会影响页面布局,特别是在聊天、评论等需要输入的场景中。UniApp 提供了多种方式来监听键盘状态变化,本文基于实际项目中的聊天页面代码,详细介绍如何实现键盘监听功能。

核心事件

@keyboardheightchange

这是 UniApp 中最重要的键盘监听事件,当键盘高度发生变化时会触发。

javascript 复制代码
// 事件对象结构
{
  detail: {
    height: number,    // 键盘高度(像素)
    duration: number   // 动画持续时间(毫秒)
  }
}

完整实现代码

模板部分 (Template)

vue 复制代码
<template>
    <view class="chat-page page-content">
        <!-- 消息列表 -->
        <scroll-view class="w-common chat-page-messages page-content-body" scroll-y scroll-with-animation> 测试键盘 </scroll-view>

        <!-- 输入框 -->
        <view class="chat-page-input" :style="style">
            <input class="input-field" v-model="inputText" placeholder="请输入消息..." :adjust-position="false" @confirm="sendMessage" @keyboardheightchange="handleKeyboardheightchange" />
            <view class="send-btn" :class="{disabled: !inputText.trim()}" @click="sendMessage"> 发送 </view>
        </view>
    </view>
</template>

脚本部分 (Script)

javascript 复制代码
<script setup>
import { ref, computed } from 'vue';
import lodash from 'lodash';

// 响应式数据
const inputText = ref('');
const keyboardHeight = ref(0);

// 计算样式 - 根据键盘高度动态调整底部内边距
const style = computed(() => {
    const flag = keyboardHeight.value > 0;
    const height = flag
        ? `calc(20rpx + ${keyboardHeight.value}px)`
        : `calc(env(safe-area-inset-bottom))`;
    return `padding-bottom: ${height};`;
});

// 发送消息的核心逻辑
const sendMessage = async () => {
    if (!inputText.value.trim()) return;

    // 这里添加发送消息的业务逻辑
    console.log('发送消息:', inputText.value);

    // 清空输入框
    inputText.value = '';

    // 隐藏键盘
    uni.hideKeyboard();
};

// 键盘高度变化处理函数(使用防抖优化)
const handleKeyboardheightchange = lodash.debounce((e) => {
    console.log('键盘高度变化:', e.detail);
    keyboardHeight.value = e.detail.height;

    // 可以在这里添加其他业务逻辑
    // 比如:滚动到底部、调整页面布局等
}, 100);
</script>

样式部分 (Style)

scss 复制代码
<style lang="scss" scoped>
.chat-page {
    height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: #f5f5f5;

    &-messages {
        flex: 1;
        overflow-y: auto;
    }

    // 输入框区域
    &-input {
        background-color: #fff;
        padding: 20rpx 32rpx env(safe-area-inset-bottom);
        border-top: 1rpx solid #e5e5e5;
        display: flex;
        align-items: center;
        position: relative;
        transition: padding-bottom 0.3s ease-out; // 添加过渡动画

        // 输入框
        .input-field {
            flex: 1;
            background-color: #f8f8f8;
            border-radius: 20rpx;
            padding: 20rpx 32rpx;
            font-size: 32rpx;
            border: none;
            outline: none;
            margin-right: 20rpx;

            &::placeholder {
                color: #999;
            }
        }

        // 发送按钮
        .send-btn {
            min-width: 120rpx;
            height: 80rpx;
            background-color: #95ec69;
            border-radius: 40rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 28rpx;
            color: #fff;
            font-weight: 500;
            padding: 0 24rpx;
            transition: all 0.2s ease;

            &:active {
                background-color: #7dd85a;
                transform: scale(0.98);
            }

            &.disabled {
                background-color: #e5e5e5;
                color: #999;
                cursor: not-allowed;
            }
        }
    }
}
</style>

关键配置说明

1. input 组件配置

vue 复制代码
<input :adjust-position="false" // 关键:禁用自动调整位置 @keyboardheightchange="handleKeyboardheightchange" />

重要提示 :必须设置 :adjust-position="false",否则键盘弹出时页面会自动调整,影响我们的自定义监听逻辑。

2. 布局说明

重要说明 :本实现使用的是 flex 布局 ,通过 display: flexflex-direction: column 来实现页面结构:

scss 复制代码
.chat-page {
    height: 100vh;
    display: flex; // 使用flex布局
    flex-direction: column; // 垂直方向排列
}
  • 消息列表区域:flex: 1 占据剩余空间
  • 输入框区域:固定高度,通过动态 padding-bottom 适配键盘

3. 防抖处理

javascript 复制代码
const handleKeyboardheightchange = lodash.debounce((e) => {
    keyboardHeight.value = e.detail.height;
}, 100);

使用防抖函数避免键盘高度频繁变化时的性能问题。

4. 动态样式计算

javascript 复制代码
const style = computed(() => {
    const flag = keyboardHeight.value > 0;
    const height = flag ? `calc(20rpx + ${keyboardHeight.value}px)` : `calc(env(safe-area-inset-bottom))`;
    return `padding-bottom: ${height};`;
});

根据键盘高度动态计算底部内边距,确保输入框不被键盘遮挡。

兼容性说明

平台 支持程度 备注
微信小程序 ✅ 完全支持 推荐使用
H5 ⚠️ 部分支持 部分浏览器可能不支持
App ✅ 完全支持 iOS/Android 都支持
支付宝小程序 ✅ 完全支持
百度小程序 ✅ 完全支持

最佳实践

1. 性能优化

  • 使用防抖函数避免频繁触发
  • 合理设置过渡动画时间
  • 避免在键盘事件中进行复杂计算

2. 用户体验

  • 添加平滑的过渡动画
  • 考虑安全区域适配
  • 处理键盘弹出时的页面滚动

3. 兼容性处理

  • 在不同平台进行测试
  • 提供降级方案
  • 处理异常情况

常见问题

Q: 为什么设置 adjust-position="false" 后页面布局异常?

A: 这是正常的,需要手动处理键盘高度变化,通过监听 keyboardheightchange 事件来调整布局。

Q: 键盘高度获取不准确怎么办?

A: 可以使用 uni.getKeyboardHeight() API 获取准确的键盘高度,并在 keyboardheightchange 事件中进行校正。

Q: 如何优化键盘弹出时的性能?

A: 使用防抖函数、避免在事件处理中进行 DOM 操作、合理设置 CSS 过渡时间。

总结

通过监听 @keyboardheightchange 事件,我们可以精确控制键盘弹出时的页面布局,提供更好的用户体验。关键是要设置 adjust-position="false" 并正确处理键盘高度变化,结合防抖优化和动态样式计算,实现流畅的键盘交互效果。

相关推荐
_一两风3 小时前
Vue3 常用指令介绍
vue.js
Z_ One Dream3 小时前
React 和 Vue 如何选择?(2026 年)
javascript·vue.js·react.js
Restart-AHTCM3 小时前
前端核心框架vue之(路由核心案例篇3/5)
前端·javascript·vue.js
天蓝色的鱼鱼3 小时前
高效开发之选:六款优秀的Vue3开源后台模板全面解析
前端·vue.js
2501_915909064 小时前
App Store 上架完整流程解析,iOS 应用发布步骤、ipa 文件上传工具、TestFlight 测试与苹果审核经验
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_916008894 小时前
iOS 26 全景揭秘,新界面、功能创新、兼容挑战与各种工具在新版系统中的定位
android·macos·ios·小程序·uni-app·cocoa·iphone
知识分享小能手10 小时前
React学习教程,从入门到精通,React 单元测试:语法知识点及使用方法详解(30)
前端·javascript·vue.js·学习·react.js·单元测试·前端框架
Ares-Wang12 小时前
Vue3 》》vite》》TS》》封装 axios ,Promise<T>
vue.js·typescript
PineappleCoder13 小时前
搞定用户登录体验:双 Token 认证(Vue+Koa2)从 0 到 1 实现无感刷新
前端·vue.js·koa