H5 页面 ios 输入框无法唤起的一种解决方案

926 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

首先声明,这不是一种完美的解决方案,也并非我原创,在这里只是分享给正在寻找解决方案的朋友,希望能够解决你的问题。

问题背景

在一个项目中可能会遇到这种场景,点击主页的搜索框然后会跳转到一个专用的搜索页进行搜索,此时输入框会被唤起,就比如淘宝和京东的主页都有这样的场景。但在 H5 页面中这样做会有一个问题,ios 的输入框无法被正常唤起,这是由 ios 的安全机制所导致的,输入框的唤起必须通过用户手动触发,所以这也是为什么跳转到另外一个页面后输入框没被自动唤起的原因。

解决办法

假设跳转前的页面为 A 页面,跳转后的页面为 B 页面,方法就是先把你的输入框抽成一个组件,然后在 A 页面中引入,在跳转页面之前去手动唤起输入框,并且记得把组件的样式设置为不可见,但这里要注意不可见的方式不能是用 v-if 或者 v-show 或 display: none,可以把它的样式设置为长宽都为零然后给一个 absolute 定位移到页面外部,防止影响页面之前的样式。

// 这是 A 页面,代码可能不规范纯手打,明白我的意思就好
<div>
  <!-- 这里是其他内容 -->
  ...
  
  <!-- 这个是你抽的组件 -->
  <some-input
    :is-show="false"
    ref="inp"
  />
  
  <!-- 这里是一个按钮或者输入框总之是跳转到另一个页面的点击触发者 -->
  <button @click="goToSearch" />
</div>
<script>
function goToSearch() {
  this.$refs.inp.focus() // 通过 focus 主动唤起输入框
  this.$router.push(...) // 通过路由跳到另一个页面
}
</script>

在 B 页面里我们需要在生命周期比如说 activate 或 mounted 里去拿到该组件并再次调用 focus 唤起输入框。到了这一步是我看的那篇文章里的全部步骤了,但是在我这么做后,发现似乎并没有解决问题,还要在 B 页面加上一个全局守卫钩子。

// 这是 B 页面
<div>
  <!-- 这里是其他内容 -->
  ...
  
  <!-- 这个是你抽的组件 -->
  <some-input
    :is-show="true"
    ref="inp"
  />
  
</div>
<script>
activated () { // 生命周期方法
  this.$refs.inp.focus() // 通过 focus 主动唤起输入框
}
beforeRouteEnter (to, from, next) { // 进到路由前调用
  next(vm => {
    if (vm.$refs.inp) {
      vm.$refs.inp.focus()
    }
  })
}
</script>

到了这里,不出意外应该是可以唤起输入框了,以上的代码是尽可能简化的结果,只保留最核心逻辑,明白意思就好。

还存在的问题

这种方法虽然能够解决 ios 输入框无法唤起的问题,但是在某些情况,就比如你第二个页面资源很多,跳转比较慢,那么因为你在第一个页面就唤起了输入框,就会导致看起来跳转有一个十分明显的卡顿,这个问题我想过一些方法,但最后都不生效,所以要是有朋友有更好的解决方法欢迎留言。