叙述难题
<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
部件文本框弹出来软件电脑键盘。具体情况实行以上姿势弹出对话框软件电脑键盘遮住了文本框,不能正常在输入文本具体内容。展现如下图所示:
处理问题
解决策略
- 网页页面无下拉列表
moveTop相当于100vh
- (kbdHeight
inputBottomY
),三个系数的计算结果可想而知popup必须向上移动数值(负数)。
流程步骤:监视文本框focus
事情;计算节点inputBottomY数值;edit-template-item
部件开启moveTop
事情this.$emit('moveTop', { top: moveTop })
;网页页面特定方式接受moveTop
事件传值,从而使popup向上移动moveTop
(px)。 - 网页页面有下拉列表
根据上边的无下拉列表版本号,发觉在一屏内就容易解决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没有明显卡屏状况)