2018年のbeforeunloadイベントハンドラーの書き方メモ
2018年のbeforeunloadイベントハンドラーの書き方メモ:
ブラウザ自身またはタブを閉じる時に、大事な未保存情報がある場合、
今回はreactで
ネットで調べるとよく出てくる記事には、マルチブラウザをサポートするために、
ブラウザの裏仕様がわかりませんが、一旦標準に書いてある
ブラウザ自身またはタブを閉じる時に、大事な未保存情報がある場合、
beforeunload
イベントハンドラーを登録することで、閉じる処理を止めて確認ダイアログを表示することが出来ます。今回はreactで
beforeunload
ハンドラーを書く時にはまったことをメモします。
結論
- 確認ダイアログの表示・非表示と表示するメッセージのコントロールは
beforeunload
ハンドラーのevent.returnValue
だけでコントールすれば良い。 beforeunload
ハンドラーでメッセージ文字列を返すような実装だと、変な動きがあるからです。
環境
- Win7+IE11
- MacOS 10.13.5 + Chrome 70.0
reactでの書き方
export default class MyComp extends React.Component { constructor(props) { super(props); this.handleBeforeUnload = this.handleBeforeUnload.bind(this); } componentWillMount() { // 登録 window.addEventListener('beforeunload', this.handleBeforeUnload); } componentWillUnmount() { // 解除 window.removeEventListener('beforeunload', this.handleBeforeUnload); } handleBeforeUnload(e) { if (this.props.hogeObject) { // 仕様標準のメソッドを呼び出す e.preventDefault(); // returnValueに画面に表示したいメッセージを設定(Chromeはそれを無視してブラウザ定義のメッセージを表示) e.returnValue = '未保存のデータがありますが、本当に閉じますか?'; } } // ... }
- 該当条件に当たった場合、e.returnValueにメッセージ文字列を設定すると、閉じる動作が停止されます。
-
e.preventDefault()
が仕様標準のお薦めなので、念のため書きます。
次のような書き方でまった!!!
ネットで調べるとよく出てくる記事には、マルチブラウザをサポートするために、e.returnValue
とハンドラーの戻り値を両方返すようなお薦め実装がありますが、実に試してみたら、下記のような変な動きがあることがわかりました。- 最初は
hogeObject
がない状態で、確認ダイアログなしで、タブを閉じれます。 - 一旦
hogeObject
がある状態にして、タブを閉じると確認ダイアログが表示されます。(ここまでまた良い) - 他の画面に遷移してから、もう一回この画面を表示して、
hogeObject
がない
状態でタブを閉じると、確認ダイアログが表示
されてしまいます。 - デバッグしてみたら、
handleBeforeUnload
は初回と同じように空白文字列を返しています。 - 戻り値が空白でも、初回と違って確認ダイアログを表示するのが何故でしょうか?ブラウザがURL単位で覚えたのかな?
handleBeforeUnload(e) { let msg = ''; if (this.props.hogeObject) { // 仕様標準のメソッドを呼び出す e.preventDefault(); // returnValueに画面に表示したいメッセージを設定(Chromeはそれを無視してブラウザ定義のメッセージを表示) msg = '未保存のデータがありますが、本当に閉じますか?'; } e.returnValue = msg; return msg; }
解決
ブラウザの裏仕様がわかりませんが、一旦標準に書いてあるe.returnValue
に戻り値を設定するように修正したら、今回の問題を解決しました。
コメント
コメントを投稿