用户填到手机号一半,页面滚到一半高度,挽留弹窗弹出来,焦点跳到弹窗按钮,回去后输入框只剩前三位。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

let fired = false;
window.addEventListener('scroll', () => {
  if (fired || document.activeElement.matches('input, textarea')) return;
  if (scrollY / document.body.scrollHeight > 0.5) { fired = true; openRetainModal(); }
}, { passive: true });

弹窗用 scroll 事件触发,判断阈值只算了一次滚动位置,用户边滚边输入时会被反复命中。弹窗打开时又把焦点强制移到主按钮,输入框里未提交的组合内容被截断。这一点先确认清楚,后面就不用反复试。

「挽留弹窗打断输入」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。

具体做法是,滚动监听加防抖,并且只在焦点不在表单内时触发;弹窗打开前判断当前是否正在填写,命中就延后到提交完成或离开页面;不要在弹窗打开时抢焦点,除非用户主动点击。

改完照着核一遍,在输入框里打字并滚动页面,弹窗不再出现,提交完成后再滚才会弹出一次。

作者 9823189