今日、モバイル H5 ページを開発しているときに、IOS 上でキーボードを格納するとインターフェイスが元の位置に戻らないという問題に遭遇しました。問題と症状については、以下で詳しく説明します。
ページ構造問題のページはフォーム構造です。つまり、ユーザーがメール情報を入力するための div の下に 4 つの入力フォームがある構造と似ています。似ている:
<div> <input type=text placeholder=都道府県、市、郡を入力してください/> <input type=text placeholder=住所を入力してください/> <input type=text placeholder=名前を入力してください/> < input type=text placeholder=住所/連絡先番号を入力してください/></div>
スクリーンショットは次のとおりです。
キーボードを開くとページが自動的に上に移動しますユーザーが携帯電話で連絡先番号を入力すると、iPhone のキーボードがポップアップします。このとき、ユーザーが電話番号の入力ボックスを表示できるようにするために、ページ全体が iPhone 上で上に移動します (そうでない場合はキーボード)。電話入力ボックスをカバーします)。この時点では、ページの上部は実際にはビューポートから離れた部分にあります (インターフェイスから入力ボックスの行が消えているのがわかります)。
キーボードを閉じるとページを元の位置に戻すことができませんただし、ユーザーが入力を完了してキーボードを閉じると、キーボードをしまってもページの位置は復元されません。
問題分析実際、これは、キーボードが格納されたときにページの一部がビューポートからスクロールアウトするのを iOS が防止できないことが原因で発生します。この時点で、ユーザーは指でページをドラッグして戻すことができます。
しかし、結局その経験は良くありませんでした。
この問題を解決するには、ユーザー カーソルが入力ボックスから離れたときにwindow.scrollTo(0, 0)
を呼び出してページをスクロールし、ビューポートの上部に揃えることで、ページ ホーム効果を実現できます。
ここでの問題は、フォーム内の 4 つの入力ボックスすべてにブラー イベントを追加し、ハンドラーでwindow.scrollTo
を呼び出すことです。ただし、Vue の@blur
を通じて追加するか、DOM 操作を通じて追加するかに関係なく、4 つのイベント リスナーを追加する必要があり、これはあまりエレガントではありません。当然、イベント プロキシの使用を考えました。
つまり、イベント リスナーを最上位の要素に配置し、トリガーを待機する inputBlur 関数を定義します。
<div @blur=inputBlur> <input type=text placeholder=都道府県、市、郡を入力してください/> <input type=text placeholder=住所を入力してください/> <input type=text placeholder=住所を入力してくださいname/> <input type=text placeholder=連絡先番号を入力してください/></div>
その結果、イベント リスナーが起動に失敗していることがわかりました。その理由は、入力ボックスのblur
イベントがバブルできないためです。
クエリを実行した結果、2 つの DOM イベントfocus
とblur
仕様に含めることはできないことがわかりました。これと同様に、バブルする可能性のある他の 2 つのイベントfocusin
とfocusout
があります。
インターネット上のいくつかの記事では、 focusin
とfocusout
IE ブラウザでのみサポートされる DOM イベントであると述べられていました。実際、MDN ドキュメントを見ると、これら 2 つのイベントが DOM 3 仕様の標準となっており、多数のブラウザーでサポートされていることがわかります。
そこで、この二つのイベントを通じて問題を根本的に解決するために、 focusout
変更しました。
<div @focusout=inputBlur> <input type=text placeholder=都道府県、市、郡を入力してください/> <input type=text placeholder=住所を入力してください/> <input type=text placeholder=住所を入力してくださいname/> <input type=text placeholder=連絡先番号を入力してください/></div>
次に、イベント ハンドラーを実装します。
inputBlur(e) { // まず、イベントをトリガーするターゲット要素が入力ボックスであるかどうかを判断します。入力ボックスの動作のみに注目します。 if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') { window.scrollTo(0,0) };
現時点では、入力ボックスに内容を入力し、キーボードの [完了] をクリックしてキーボードを閉じると、その効果は期待どおりになります。
ただし、携帯電話でテストした結果、 电话输入框
から姓名输入框
に直接切り替えると、ページが不安定になることがわかりました。分析を続けてみましょう。
実際、切り替え時に 2 つの入力ボックスがジッターする理由も非常に単純です。上記の 2 つの入力ボックスを切り替えると、ページは最初に电话输入框
のblur
イベントをトリガーし、次に姓名输入框
のfocus
イベントをトリガーするためです。この場合、ぼかしが発生するとwindow.scrollTo(0,0)
がトリガーされ、ページが下にスクロールされ、 姓名输入框
がフォーカスされるため、キーボードがポップアップし続けます。ページが再び上に移動します。
実際、2 つの入力ボックスを切り替えるとき、最初の入力ボックスがぼやけているときにwindow.scrollTo
動作をトリガーする必要はありません。 そこで、入力ボックスの切り替え操作が発生したときに、最初の入力ボックスの動作を遮断できるようにコードを変更しましょう。ここでは setTimeout を使用して解決します。
<div @focusout=inputBlur @focusin=inputFocus> <input type=text placeholder=県、市、郡を入力してください/> <input type=text placeholder=住所を入力してください/> <input type=text placeholder=名前を入力してください/> < input type=text placeholder=連絡先番号を入力してください/></div>
inputBlur(e) { // まず、イベントをトリガーするターゲット要素が入力ボックスであるかどうかを判断します。入力ボックスの動作のみに注目します。 if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') { // 入力ボックスはフォーカスを失うため、IOS キーボードをキーボードから押し出す必要があります。ページの一部をスクロールして復元します。ページをウィンドウの一番上までスクロールし、位置を合わせます console.log('set timer') this.timer = setTimeout(() => { console.log('timer Trigger') window.scrollTo(0,0); }, 0) } }, inputFocus(e) { // フォーカスの場合、前の入力ボックスのタイマーを削除 if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') { clearTimeout(this.timer) } }
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。