Angular アプリの画面遷移を実現するブックマークレットを作る
とある Angular 製アプリの使い勝手を向上すべく、ブックマークレットを駆使して独自の追加メニューを実装してみた。
document.body.insertAdjacentHTML('beforeend', `<a href="/admin-menu" style="position: absolute; top: 0; right: 0; background: #fff;">Admin Menu</a>`);
上のコードをブックマークレットとして実行すると、ページ右上に「Admin Menu」というリンクが登場する。リンク先は /admin-menu
としており、押下すると通常のリンクとしてページ遷移が発生する。
コレでもまぁ良いのだが、SPA なのにページ全体が再読み込みされてしまうのはちょっと鬱陶しい。せっかくなら Router Link による画面遷移を実行したいのだが、ブックマークレットのように外部のスクリプトから router.navigateTo()
メソッドなどは叩けないだろうし、ということで違う方法を調べた。
色々試したところ、history.back()
ないしは history.forward()
だと SPA としての画面遷移が発火することが判明。対して history.go()
は location.reload()
と同じく、F5 ボタンを押した時のようなページ全体の再読み込みが発生してしまった。
で、history.back()
を利用して任意の URL に飛ばしてやるには、history.pushState()
を2回実行する、という方法でなんとかなった。
つまり以下のようなコードにすると、Angular の Router Link による、SPA としての画面遷移が実現できる。
document.body.insertAdjacentHTML('beforeend', `
<a style="position: absolute; top: 0; right: 0; background: #fff;"
href="javascript:history.pushState({},'','/admin-menu'); history.pushState({},'','/admin-menu'); history.back();">Admin Menu</a>`);
insertAdjacentHTML()
や innerHTML
では、script
要素が埋め込めなかった。なので遷移用の関数を作っておいて onclick
で呼ぶ、みたいな実装は失敗した。href
属性に javascript:
から繋げてインラインにコードを書いておけば保持された。
最終的にブックマークレットとして動かすため、次のように書いて完成。
javascript:(x=>document.body.insertAdjacentHTML('beforeend',`<a style="position:absolute;top:0;right:0;background:#fff" href="javascript:history.pushState({},'','/admin-menu');history.pushState({},'','/admin-menu');history.back()">Admin Menu</a>`))();
やりたいことは一応実現できたのでよきよき。試してはいないけど、React Router や Vue Router など、他の SPA でも使えるかもしれない。