MutationObserverはResizeObserverの代わりになるのか?検証編

2019年2月16日

Javascript テクノロジー プログラミング

結論から言うと「できない」です。 今回は、何故できないかを検証する記事なので、解決方法が見たい人は早々に退散してください。 技術好奇心のある人向けの記事にしているので、自分のスキルの肥やしにしてくださいませ。

この記事を書くきっかけ

まずは、前回記事の「Elementのリサイズ監視にはResizeObserver」を見てもらうと、ResizeObserverが2019年2月現在、GoogleChromeでしか動作しない命令で有ることがわかり、兄弟関数のMutationObserverで同じことをやろうとしたことがきっかけです。 前回記事 : Elementのリサイズ監視にはResizeObserver そして、簡易に考えてサンプルプログラムを作ってみたところ、あまりの出来なさ加減に愕然としてしまいました。 そもそも、特定のエレメントがイベント操作によってサイズ変動や内部情報変更が行われる際に、それを事前にセットしておいた監視システムで察知するという事がやりたかったんですが、具体的に言うと、ページ内のサイドメニューがボタン一つで拡縮する仕様であった場合、window.resizeが発動せず、エレメントのサイズが切り替わったというイベントを取得したかったことがこの記事の起因するところです。 安易にonresizeでできるとタカをくくっていたのが恥ずかしくなる感じですが、MutationObserverで監視すればいいとこれも簡易に考えていたのがさらに自己嫌悪です。

技術検証

前回記事のresizeObserverをMutationObserverに切り替えたソースコードは以下のとおりです。 <html> <head> <meta charset="utf-8"> <style type="text/css"> #resize{ width:100px; height:100px; background-color:red; cursor:pointer; } #resize:hover{ width:150px; height:150px; background-color:blue; } #resize:hover:before{ content:"hoge-hoge"; color:white; } </style> </head> <body> <h1>ResizeObserver</h1> <div id="resize"> </div> <script> var ob = new MutationObserver(function(m1,m2){ console.log(m1); // console.log(m2); }); ob.observe( document.getElementById("resize") , { attributes: true, childList: true, subtree: true, characterData: true, attributeFilter: [ "style", "offsetHeight", "clientHeight", "scrollHeight" , "height" , "hover" ] }); document.getElementById("resize").style.width = "100px"; </script> </body> </html> これをデバッグコンソールで見ていると、style.widthで値を挿入している箇所では、イベント発動しているのですが、CSSのhoverによるサイズ変更に対してはイベント発動していないことがわかります。 これは死活問題であり、かなりの想定外でした。 ようするに、エレメントに対して、atrributeをjsで操作した時は、イベント発動するのだけれど、CSSの擬似クラス系におけるスタイル変更はイベントに引っかからないのだ!!! ResizeObserverで出来ていただけにこれは痛い!!

検証1

そして、ソースコードに見られる各種検証履歴としては、「AttributeFilter」に対して、offsetWidth,clientWidth,scrollWidth,widthを入れてみたが・・・ 反応せず・・・

検証2

optionに"characterData: true,childList: true,subtree: true"をセットして、:before疑似属性でcontent:"hoge-hoge"と内部要素の変更を試みてみたが・・・ 反応せず・・・

検証3

もちろん、javascriptでelement.textContent = "hoge-hoge";とやってみると・・・ きちんと反応します。

結論と解決に向けた思考

今回の実験を元に、現時点でMutationObserverに頼りすぎると結構痛い思いをすることになる。という結論を得ました。 もちろん、setIntervalなどによる、随時検証を行うのも躊躇してしまうので、今のところは、サイドメニューが拡縮するための起動ボタンのclickイベントに連動して、対象コンテンツのサイズを手動で計算して切り替えるようにしました。 ん〜〜〜・・・あまりスッキリしない結果にストレスが増しました。 実はネットで調べても、cssの疑似要素に対してのMutationObserverを行っているサイトはなく、どのサイトも同じ設定で行っている始末です。 改めて同じ記事をネットで書くなよ〜と憤ってしまいましたが、自分でなんとかできると、いい記事が書けるのではないかという考えから、 ぜって〜なんとか解決したやる〜〜〜。という思いで本日は一旦終わりにします。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。