[Javascript] IE11ではonStorageイベントの挙動が異なる | パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

開発の解決方法や新しい手法の情報を、パークのエンジニアが提供します。パークのエンジニアが必要な場合は、ぜひお気軽にお問い合わせ下さい。 株式会社パーク:http://www.pa-rk.co.jp/

こんにちは!パーク社員のゆんぼうです。

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イベントの挙動が異なるため、複数タブの同期をとる場合は注意が必要です。

 

以上です。