Materialize 、モダンっぽい Web サイトを作れるので、
個人的には Bootstrap よりは最近使うようになりつつあります。
「Bootstrap より軽いし……」と書こうとして実際にいま測ってみたらそうでもなかったですが(笑)
1. Bootstrap vs. Materialize (ファイルサイズ比較)
1-1. Bootstrap
- bootstrap.min.js (v4.1.3) : 20.56KB
- bootstrap.min.js (v4.1.3) : 13.76KB
- jquery-3.3.1.slim.min.js : 23.47KB
- popper.min.js (v1.14.3) : 6.8KB
Total: 64.59KB
1-2. Materialize
- materialize.min.css (v1.0.0) : 19.63KB
- materialize.min.js (v1.0.0) : 39.9KB
Total: 59.53KB
Materialize の JavaScript は jQuery を内包しているので、そのぶん大きくなっていますね。
読み込むファイル数は少ないので、そのぶんコストは低いですが、思ったより容量に差はなかったです。
閑話休題。本題にいきましょう。
2. Materialize の JavaScript ライブラリを TypeScript で使いたい
例えば materialize-css の Navbar Component の Dropdown を使いたいときには、
Dropdown のドキュメントにある通り、
// ドキュメント通りに dropdown-trigger class を設定し、以下の script を末尾などに記述 document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.dropdown-trigger'); M.Dropdown.init(elems, {}); }); // jQuery を呼び出している場合は以下の 1 行で済む $('.dropdown-trigger').dropdown();
上のどちらかの方法でドロップダウンをアクティブにしなくてはいけません。
HTML の最後に script タグを使って、
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.dropdown-trigger'); M.Dropdown.init(elems, options); }); </script>
こんな感じで書いてあげてもいいわけですが、
せっかくなら ts ファイルや tsx ファイル内で呼び出してあげたい。その方法です。
3. 答え
3-1. npm install -D @types/materialize-css
前置きが長くなりましたが、以下のようにライブラリをダウンロードすればOKです。
npm i -S materialize-css npm i -D @types/materialize-css
materialize-css だけでなく、
@types/materialize-css を入れているのが一番のポイントです。
これがないと TypeScript でのコンパイルに失敗してしまいます。
なお、古い記事だと npm i -S materialize-css@next
で入れている記事がありますが、
2019年5月現在では、 npm i -S materialize-css
で入るのは 1.0.0 、
npm i -S materialize-css@next
で入るのは 1.0.0-rc.2 と、
next を付けるほうがむしろ古いバージョンが入ってしまうのでお気をつけください。
3-2. import M from 'materialize-css'
あとはいつも通りに、 tsx ファイルや ts ファイルの先頭で import してあげれば OK です。
import M from 'materialize-css';
2. の項で書いた例のように、
var elems = document.querySelectorAll('.dropdown-trigger'); M.Dropdown.init(elems, {});
を適当な場所で書くことにより Dropdown の初期化をおこなうこともできますが、
ドキュメントの例にあるようなクラス名(dropdown-trigger)をそのまま使う場合でしたら、
M.AutoInit();
でカンタンに済ませることも可能です。(参考: https://materializecss.com/auto-init.html )
どのコンポーネント、そして class 名だと初期化されるかは元のコードを読むといいでしょう。
https://github.com/Dogfalo/materialize/blob/efa0aee/js/global.js#L106-L135
3-3. React で扱う場合の Tips
M.AutoInit();
は componentDidMount 内で呼び出すと良いでしょう。
(※ constructor 内で呼び出すと失敗します。constructor は HTML render がおこなわれる前に走るためです)
public componentDidMount(): void { M.AutoInit(); }
M.AutoInit();
は便利ですが、すべてのコンポーネントに関する init がおこなわれるわけではありません。
例えば M.updateTextFields();
もその一つです。(参考: 『Text Inputs』 の『Prefilling Text Inputs』の項)
これは、Text Input Form にすでに文字が入力されている場合には、ラベルを上に移動しておいてくれるメソッドです。
https://github.com/Dogfalo/materialize/blob/efa0aee/js/forms.js#L3-L21
使用しないとこうなる:
使用するとページ表示時にこうなってくれる:
これは M.AutoInit();
から呼び出されないことがコードからわかりますので、
入力フォームのあるページでは M.updateTextFields();
を使ってあげるといいです。
私の書いているコードでは、input フォームの defaultValue を非同期通信で取ってくるために
render のされ直しが発生してしまうため、
componentDidMount 内ではなく componentDidUpdate 内で呼び出してあげています。
public componentDidUpdate(): void { M.updateTextFields(); }
4. おしまい
React を今まで避けて生きてきたんですが、
かんたんな Go (Gin) + React のアプリケーションを作ってみようとさわってみたら
ちょっとずつわかってきました。
Redux には触れていないですが、今のところバケツリレーも大規模になっていないので、
今回は使わないでもいけそうです。
ついでに TypeScript も導入し、数年ぶりにさわっていますが、
慣れていない Go + 慣れていない React + 慣れていない TypeScript の組み合わせでちょこちょこ苦しんでいます(笑)
型チェックのために書く量は増えるし、参考資料そのままで書けない場合もあり大変です。
とても勉強になっているので、もう少しがんばってみます!