こんにちは!パーク社員のゆんぼうです。
Webアプリ開発のクロスブラウザ対応したときに注意したいことを紹介します。
今回は、Javascriptの「onStorage」イベントについてです。
動作確認した環境
OS: Windows 10 Pro
| ブラウザ名 | バージョン |
|---|---|
| Google Chrome | 62.0.3202.94 |
| Mozilla Firefox | 57.0 |
| Microsoft Edge | 41.16299.15.0 |
| Microsoft Internet Explorer (IE11) | 11.64.16229.0 |
onstorageとは
Web Storageの1つである「LocalStorage」に変化が起こった場合にイベントが発生します。
https://developer.mozilla.org/ja/docs/Web/API/WindowEventHandlers/onstorage
以下のデモページをブラウザのタブを2つにしてそれぞれ表示してみてください。
LocalStorageのsetItem、getItem、removeItem, clear の動作が確認できます。
onStorageを確認するためには、「input:」テキストボックスに文字を入力して「setItem」ボタンを押下してください。LocalStorageの値が変わり、別のタブの「Log:」イベントが通知されます。
「abcdefg」をsetItemにすると別のタブに以下のログが表示されます。
[23:33:12] onstorage: key=itemKey, oldValue=null, newValue=abcdefg
以下のような実装になっています。
$('#setItemButton').on('click', function () {
var itemValue = $('#itemInput').val();
localStorage.setItem('itemKey', itemValue);
});
window.onstorage = function (e) {
log('onstorage: key=' + e.key + ', oldValue=' + e.oldValue + ', newValue=' + e.newValue);
};
ブラウザ毎のonStorageの挙動
クロスブラウザ対応で注意したいこととして、IE11とその他のブラウザでは、onStorageイベントの挙動が異なります。IE11では、setItemを実行したタブと別のタブの両方にonStorageイベントが通知されます。その他のブラウザでは、別のタブの片方のみ通知されます。
| ブラウザ名 | localStorageの値を変えたタブ | その他のタブ |
|---|---|---|
| Google Chrome | 通知されない | 通知される |
| Mozilla Firefox | 通知されない | 通知される |
| Microsoft Edge | 通知されない | 通知される |
| Microsoft Internet Explorer (IE11) | 通知される | 通知される |
複数タブの同期 (onChange)
onStorageイベントを利用して、複数タブでテキストボックスの値を同期してみたいと思います。
以下のデモページをブラウザのタブを2つにしてそれぞれ表示してみてください。
「input:」テキストボックスに文字を入力すると、別のタブにその内容が反映されています。テキストボックスでonChangeイベントが通知されるとlocalStorageのsetItemを実行しています。そのため、別タブにonStorageイベントが通知されて、別タブのテキストボックスに反映されます。
$('#itemInput').on('change', function () {
// テキストボックスのフォーカスが外れたタイミングで呼ばれる
var itemValue = $('#itemInput').val();
localStorage.setItem('itemKey', itemValue);
});
window.onstorage = function (e) {
log('onstorage: key=' + e.key + ', oldValue=' + e.oldValue + ', newValue=' + e.newValue);
$('#itemInput').val(e.newValue);
};
複数タブの同期 (onKeyup)
onChangeイベントと同様に、onKeyupイベントでテキストボックスの値を同期してみたいと思います。
以下のデモページをブラウザのタブを2つにしてそれぞれ表示してみてください。
しかし、onKeyupイベントで実装された場合、IE11では、「ローマ字入力」で日本語を入力すると正しく入力できません。onChangeイベントでは、テキストボックスのフォーカスが外れたタイミングで通知されますが、onKeyupイベントは、キーボードのキーを離したタイミングで通知されます。そのため、onKeyupイベントでsetItemを実行すると、そのタブにonStorageイベントが通知され、入力中のテキストボックスに対して値が更新されてしまいます。例えば、「こ」と入力した場合は、onStorageイベントには「k」がnewValueとして通知されるため、タイミングによってはテキストボックスに「k」が表示されてしまうことがあります。
$('#itemInput').on('keyup', function () {
// キーボードのキーを離したタイミングで呼ばれる
var itemValue = $('#itemInput').val();
localStorage.setItem('itemKey', itemValue);
});
window.onstorage = function (e) {
log('onstorage: key=' + e.key + ', oldValue=' + e.oldValue + ', newValue=' + e.newValue);
// IE11では、テキストボックス入力中に、newValueで上書きされる
$('#itemInput').val(e.newValue);
};
このように、IE11ではonStorageイベントの挙動が異なるため、複数タブの同期をとる場合は注意が必要です。
以上です。