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" 并正确处理键盘高度变化,结合防抖优化和动态样式计算,实现流畅的键盘交互效果。

相关推荐
前端开发爱好者5 小时前
尤雨溪官宣:"新玩具" 比 Prettier 快 45 倍!
前端·javascript·vue.js
欧阳呀5 小时前
Vue+element ui导入组件封装——超级优雅版
前端·javascript·vue.js·elementui
华仔啊8 小时前
用 Vue3 + Canvas 做了个超实用的水印工具,同事都在抢着用
前端·vue.js·canvas
Q_Q5110082858 小时前
python+uniapp基于微信小程序团购系统
spring boot·python·微信小程序·django·uni-app·node.js·php
炒毛豆8 小时前
uniapp微信小程序+vue3基础内容介绍~(含标签、组件生命周期、页面生命周期、条件编译(一码多用)、分包))
vue.js·微信小程序·uni-app
岁月宁静9 小时前
在 Vue 3.5 中优雅地集成 wangEditor,并定制“AI 工具”下拉菜单(总结/润色/翻译)
前端·javascript·vue.js
Dolphin_海豚10 小时前
@vue/reactivity
前端·vue.js·面试
菜狗的小小笔记_11 小时前
Vue3 实用技巧
vue.js
盛夏绽放13 小时前
关于 uni-app 与原生微信小程序中的生命周期 —— 一次“生命旅程”的解读
微信小程序·小程序·uni-app
知识分享小能手14 小时前
uni-app 入门学习教程,从入门到精通,uni-app 基础知识详解 (2)
前端·javascript·windows·学习·微信小程序·小程序·uni-app