Mithril.js Router の応用 - レイアウト、複数コンポーネントを考えた 実用編
例えば http://localhost/page1
というURLへのアクセスは Page1Component
を表示して、http://localhost/page2
は Page2Component
を表示したい場合です。
もし、1つの URL が1つのコンポーネントだけで構成されているなら、Mithril.js では、オフィシャルのドキュメントにも書かれている通り簡単です。
ですが、もし1つのURL が1つ以上のコンポーネントで構成されて、共通箇所が有る場合、例えばメニュー等がふくまれコンポーネントが入り組んでいる場合は、作成にコツがいります。
基本 : 1つのURLが1つのコンポーネント
おさらい。これは以下の通りで、特に説明の必要もないと思います。
m.route(document.body, '/page1', {
'/page1' : Page1Component,
'/page2' : Page2Component,
}
http://localhost/page1
から http://localhost/page2
へ切り替わるときには、<Page1Component>
の DOM は削除され、<Page2Component>
の DOMが作成されます。特に何も問題となることは無いはずです。
1つのURLが2つ以上のコンポーネントで、共通箇所が有る場合
この場合は注意が必要です。
http://localhost/page1
から http://localhost/page2
へ切り替わるときには、<Page1Component>
の DOM は削除され、<Page2Component>
の DOMが新しく作成されるのは良いとして、
問題は、共通箇所である <MenuComponent>
の DOM が削除されて、再びDOMが再作成されると厄介な問題が発生します。
具体的には <MenuComponent>
に使うようなものですから、クリックしたときにCSSアニメーションなどをつけたり、ログインユーザーなどの変数を持っていたりする場合は少なくありません。もしDOM が削除、再作成されるようなことがあれば、CSSアニメーションが途切れたり、画面のチラつきなど、なにかと問題が発生するのです。これは良くは有りません。
これらを防止するために Mithril Router では RouteResolver というものが用意されています。
この RouteResolverを使えば、同じコンポーネントのDOMを 削除、再生成 されることを防げます。
class LayoutComponent {
public view(vnode){
return (
<div>
<div class="menu">
<MenuComponent />
</div>
<div class="main">
{ vnode.children }
</div>
</div>
);
}
}
class Page1Component {
// .....
}
class Page2Component {
// .....
}
const handleOnmatch = ()=>{
window.requestAnimationFrame(()=>{
window.scrollTo(0, 0); // ページ切り替え時 スクロールバーを上部へスクロール
});
return;
};
m.route(document.body, '/page1', {
'/page1' : {
onmatch: handleOnmatch,
render: ()=>{ return <LayoutComponent><Page1Component /></LayoutComponent>; }
} ,
'/page2' : {
onmatch: handleOnmatch,
render: ()=>{ return <LayoutComponent><Page2Component /></LayoutComponent>; }
} ,
}
実際のコードを書く場合には、コンポーネントを1つにまとめる <LayoutComponent>
等のコンポネントで囲っておくのが良いでしょう。
他にも、ページが切り替わった時にブラウザは上部へスクロールするのがブラウザの一般的な動作です。onmatch
でページ切り替え時 スクロールバーを上部へスクロールするようにしています。これで、ずいんぶん印象が違ってきますので、入れておくのが良いとは思います。