Telegram Web App(Vue)键盘弹出时布局高度异常问题
解决方案
1. 监听Telegram WebApp键盘高度变化
Telegram WebApp提供了viewportChanged事件和viewportStableHeight属性,可实时获取键盘高度并调整布局:
在Chat.vue的setup函数中添加监听逻辑:
import { useTelegram } from '@vue-tg' import { onMounted, onUnmounted, ref } from 'vue' const tg = useTelegram() const messageInputEl = ref(null) onMounted(() => { const handleViewportChange = () => { // 计算键盘高度:当前窗口高度减去稳定视口高度 const keyboardHeight = window.innerHeight - tg.WebApp.viewportStableHeight // 动态调整输入框的bottom值 if (messageInputEl.value) { messageInputEl.value.style.bottom = `${keyboardHeight}px` } } // 绑定视口变化事件 tg.WebApp.onEvent('viewportChanged', handleViewportChange) // 组件卸载时移除监听,避免内存泄漏 onUnmounted(() => { tg.WebApp.offEvent('viewportChanged', handleViewportChange) }) })
同时更新Chat.vue模板,给message-input绑定ref:
<div class="chat__message-input" ref="messageInput"></div>
2. 修正CSS布局问题
- 改用
100dvh替代100vh,适配动态视口高度(键盘弹出时视口高度变化) - 将
chat__header的fixed改为sticky,配合父容器的flex布局避免错位 - 给
chat__header添加背景色,防止被下方内容覆盖 - 调整
chat__messages的内边距,避免和粘性元素重叠
修改后的SCSS:
body, html { background-color: var(--primary-color); margin: 0; height: 100dvh; overflow: hidden; } .chat { display: flex; flex-direction: column; height: 100dvh; opacity: 0; visibility: hidden; position: relative; /* 添加相对定位,配合子元素的绝对定位 */ &.is-ready { opacity: 1; visibility: visible; } &__header { display: flex; align-items: center; border-bottom: 1px solid var(--border-color); position: sticky; top: 0; z-index: 1000; background-color: var(--primary-color); /* 确保背景覆盖下方内容 */ height: 54px; /* 明确高度,方便计算消息区域的内边距 */ } &__messages { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; background-color: #f4f4f4; padding: 20px 10px; padding-top: 54px; /* 和header高度一致,避免内容被遮挡 */ } &__message-input { position: absolute; /* 改用绝对定位,依赖父容器的相对定位 */ bottom: 0; left: 0; right: 0; z-index: 1000; overflow: hidden; background-color: var(--primary-color); padding-bottom: calc(env(safe-area-inset-bottom) + 0px); transition: bottom 0.3s ease; /* 添加过渡动画,提升体验 */ } }
3. 确保正确的Viewport配置
在项目的index.html中,更新meta标签以适配Telegram WebApp:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
内容的提问来源于stack exchange,提问作者darl1ne
相关产品推荐
相关产品推荐

