由Vant Field组件得到解决IOS输入框 键盘上推问题

前言

前几天公司让写一个客户数据入录页面(就是个带了logo的表单页面),就直接选择用原生的直接上,原以为也就个把小时的事情(确实个把小时就写完了),但是测试发现ios(没有测试多个,至少qq浏览器会)会输入的时候导致页面上推严重影响用户体验。

可直接转第三部分

由开源库找到方案

Vant Field组件

通过看源码发现Field在blur事件时候会执行一个滚动事件

贴代码:reset-scroll.ts

// reset-scroll.ts
import { isIOS as checkIsIOS } from '../validate/system';
import { getRootScrollTop, setRootScrollTop } from './scroll';

const isIOS = checkIsIOS();

/* istanbul ignore next */
export function resetScroll() { // 触发blur事件后会执行该函数
  if (isIOS) {
   setRootScrollTop(getRootScrollTop());
  }
}

贴代码 system.ts

import { isServer } from '..'; // 不是很重要单纯的判断是不是服务器渲染
// ...
// 判断是不是ios 服务器渲染直接不判断
export function isIOS(): boolean {
  /* istanbul ignore next */
  return isServer
   ? false
   : /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase());
}

贴代码:scroll.ts

// 部分代码
// ...
export function getRootScrollTop(): number {
  return (
   window.pageYOffset ||
   document.documentElement.scrollTop ||
   document.body.scrollTop ||
   0
  );
}
// ...
export function setScrollTop(el: ScrollElement, value: number) {
  if ('scrollTop' in el) {
   el.scrollTop = value;
  } else {
   el.scrollTo(el.scrollX, value);
  }
}
// ...
export function setRootScrollTop(value: number) {
  setScrollTop(window, value);
  setScrollTop(document.body, value);
}
// ...

转换成原生代码 or 解决方案

逻辑

  1. 监听blur
  2. 判断是否是ios
  3. 滚动到原来的位置

代码

<style>
   input{
      /* 模拟输入框位置 */
      margin-top:500px;
   }
</style>
<input type="text" >

<script>
  // 检查是否是ios
   function checkIsIOS(){
      return /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase())
   }
   // 设置滚动元素(兼容性问题)
   function setRootScrollTop(value) {
      setScrollTop(window, value);
      setScrollTop(document.body, value);
   }
   // 设置滚动位置
   function setScrollTop(el, value) {
      if ('scrollTop' in el) {
        el.scrollTop = value;
      } else {
        el.scrollTo(el.scrollX, value);
      }
   }
   // 获取滚动位置
   function getRootScrollTop() {
      return (
        window.pageYOffset ||
        document.documentElement.scrollTop ||
        document.body.scrollTop ||
        0
      );
   }
   
   const isIOS = checkIsIOS();
   // 执行还原滚动条
   function resetScroll() { // 触发blur事件后会执行该函数
      if (isIOS) {
        //  这是滚动条位置
        setRootScrollTop(getRootScrollTop());
      }
   }
   const _input = document.querySelector('input');
    // 监听失去事件
   _input.onblur  = ()=>{
      console.log('onblur')
      resetScroll();
      // TODO: ...其他操作
   }
</script>