自定义键盘覆盖表单的坑
最近在开发Cordova+vue项目时,引用了vant-ui的数字自定义键盘,因为不是原生键盘,所以出现了键盘覆盖了表单的现象,导致使用数字自定义键盘的时候看不到自己输入了啥。
思路非常简单,既然覆盖上了,那就让表单在自定义键盘弹出的时候滚上去就OK了。
1 第一次尝试 -- scrollBy
采用了scrollBy方法。
// 键盘组件代码
methods: {
// 打开键盘的时候
handleNumberClick () {
// 弹起数字键盘
this.showNumberKeyBoard = true
// 比较下被点的输入框高度和整个页面滚动高度的高度差
// 也就是算一下输入框距离顶部的距离,如果超过360,就认为会被遮盖到
// 就向上滚一些
if (this.$refs.keyBoard.offsetTop - this.$parent.$refs.section.scrollTop > 360) {
this.scrolled = true
this.$parent.$refs.section.scrollBy({
top: 300,
behavior: 'smooth'
})
}
},
handleBlur () {
this.$emit('input',this.number)
this.showNumberKeyBoard = false
if (this.scrolled) {
// 键盘失焦,滚回来
this.$parent.$refs.section.scrollBy({
top: 0,
behavior: 'smooth'
})
this.scrolled = false
}
}
}
万万没想到,在h5和iOS上跑得很好的代码,在Android上不起作用。
然后就打了桩,发现Android竟然在报错。说不认识scrollBy.
是的,对我来讲这是个谜,我现在也不知道为什么他不认识scrollBy
2 第二次尝试 -- jquery
网上有解决方案jquery可以解决这个问题,就使用了jquery。
// 键盘组件代码
methods: {
handleNumberClick () {
this.showNumberKeyBoard = true
if (this.$refs.keyBoard.offsetTop - this.$parent.$refs.section.scrollTop > 360) {
this.scrolled = true
// 使用这种方式
$('#startInspectSection').animate({
scrollTop: 300
}, 1000);
// 或者使用这种方式
// $('#startInspectSection').scrollTop(300)
}
},
handleBlur () {
this.$emit('input',this.number)
this.showNumberKeyBoard = false
if (this.scrolled) {
// 使用这种方式
$('#startInspectSection').animate({
scrollTop: 0
}, 1000);
// 或者使用这种方式
// $('#startInspectSection').scrollTop(0)
this.scrolled = false
}
}
}
jquery解决了我的问题。随之有两个疑问:
- jquery是怎么做到的
- 怎么才能不再vue里用jquery
翻阅jquery源码,找到了这段代码。
// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
var top = "pageYOffset" === prop;
jQuery.fn[ method ] = function( val ) {
return access( this, function( elem, method, val ) {
// Coalesce documents and windows
var win;
if ( isWindow( elem ) ) {
win = elem;
} else if ( elem.nodeType === 9 ) {
win = elem.defaultView;
}
if ( val === undefined ) {
return win ? win[ prop ] : elem[ method ];
}
if ( win ) {
// 如果是window的话
win.scrollTo(
!top ? val : win.pageXOffset,
top ? val : win.pageYOffset
);
} else {
// 如果不是window的话,就直接使用了scrollTop或scrollLeft属性
elem[ method ] = val;
}
}, method, val, arguments.length );
};
});
是的,为什么要纠结于方法呢,可以使用属性啊。
3 第三次尝试 -- scrollTop属性
基于jquery的实现,使用vue来实现,就是使用scrollTop属性。
methods: {
handleNumberClick () {
this.showNumberKeyBoard = true
if (this.$refs.keyBoard.offsetTop - this.$parent.$refs.section.scrollTop > 360) {
this.originOffset = this.$parent.$refs.section.scrollTop
this.$parent.$refs.section.scrollTop = this.scrolled = this.$parent.$refs.section.scrollTop + 300
}
},
handleBlur () {
this.$emit('input',this.number)
this.showNumberKeyBoard = false
if (this.scrolled) {
this.$parent.$refs.section.scrollTop = this.originOffset
this.scrolled = 0
}
}
},
总结
要抽时间好好看看基础知识了,都是基础不牢的锅。
本文使用 mdnice 排版