Javascriptのライブラリを漁る事に少しハマっています(笑)
軽量なもので何かいいのは無いか?と思って見つけたのが「Riot.js」です。何やらカスタムタグと言うのを用いて、コンポーネント化をしやすくする作りのようです。仮想DOMではないので、以前ちょっといじったUmbrella.jsも問題なく使えるようです。学習コストも少なめで、メンテナンスもしやすそうで、使い勝手もよさそうです。しかも、公式ページは、日本語ページもある!
というわけで、今回はこれでカウンターを作成してみようと思います。
Riot.jsの設置方法
Riot.jsはnpmもあるようですが、当方の環境はNode.jsないんで、今回も無難にCDN (htmlにURLを記述し、ネット経由で毎回読み込みに行く方法)で使いたいと思います。で、実際にhtmlに貼り付けるscriptタグは以下になります。
<!-- Riot.jp とコンパイラを含める、ver 9.1.4 (2024/03/27現在) --> <script src="https://unpkg.com/riot@9/riot+compiler.min.js"></script>
次に、index.htmlです。Riot.jsの現在のバージョンでは、作ったカスタムタグ(今回は「counter」 という名前のカスタムタグ)を別ファイルから読み込む形式(昔のバージョンの事はよくわかりません、すみません)のため、index.htmも特殊になります。以下、<body>タグ内の記述です。
<body> <!-- ①「<カスタムタグ名 />」はここに別ファイルを読み込む形 -->> <counter /> <!-- ②「<counter/>」 は外部ファイルで指定 --> <script src="./counter.riot" type="riot"></script> <!-- ③Riot.js とコンパイラを含める、ver 9.1.4 (2024/03/27現在) --> <script src="https://unpkg.com/riot@9/riot+compiler.min.js"></script> <!-- ④コンパイルとマウント --> <script> (async function main() { await riot.compile() riot.mount('counter') }()) </script> </body>
①カスタムタグ設置場所
今回はカウンターを作るので、「counter」というカスタムタグを作ります。 別ファイルの読み込みになるので、設置場所の指定は、<counter></counter> ではなく <counter /> で行けるようです。
②.riotファイルの指定読込み
- 「src=”ファイル名.riot”」で別に作ったカスタムタグファイルの場所を指定
- 「type=”riot”」で type指定
以前のバージョンではこのtype指定が他の形だったようですが、現バージョンではこれでいけます。
③Riot.js とコンパイラをCDN
前述してますので割愛します。バージョンは9.1.4です。(2024/03/27現在)
④コンパイルとカスタムタグのマウント
このマウント方法も、以前バージョンよりもちょっと変わって、より複雑になっているようです。
尚、「riot.mount(‘counter’)」この部分は、第2引数にpropsの値も設定出来るようです。
riot.mount('カスタムタグ名') //この形から… riot.mount('カスタムタグ名', propsの値) //第2引数にpropsを設定出来る riot.mount('counter', { //今回はオブジェクトでtitleとverを設定 title: 'カウンター', ver: `@ riot.js ${riot.version}`, })
第2引数のpropsには色々なものを設定出来るようですが、自分にはまだ難しいので、いずれ使いこなしていこうと思います。とりあえず今回は、オブジェクトでtitleとverを設定してみました。
- Riot.jsのバージョンは「consple.log(riot.version)」などで確認できます。
カスタムタグ(.riotファイル)作成
前述の通り、カスタムタグを扱うファイルを、index.html とは別に作っていきます。拡張子は「.riot」です。
<counter> // カスタムタグの中に必要コードの記述 ~~~ // html部 <style> ~~~ // CSS部 </style> <script> ~~~ // スクリプト部 </script> </counter>
カウンターの作成
では上記に基づき、カウンタ-を作っていこうと思います。目指す形は、次のようになります。
- +と-で数値の上下をさせる
- resetボタンを設置
- 数値の増減で、背景色が白から変化
- 値が正で赤系、負で青系に徐々に変化
簡単なものではありますが、練習にはちょうど良いと思います。
html部
<counter> <p>{props.ver}</p> //①propsより値を取得 <h1>{props.title}</h1> <div id="disp"> <h2 id="h2_d">{state.count}</h2> <br> <button onclick="{() => upDown(-1)}">-</button> //②onclick="{関数}" <button onclick="{() => upDown(1)}">+</button> //③引付き関数 <button onclick="{reset}">reset</button> //③引数無し関数 </div> <style> {~~~}
あまり説明個所がありません(笑)
- ①「{変数}」で変数表示
- ②「onclick=”{関数名}”」で、クリックイベント
- ③引数付き関数は 「{() => 関数(引数)}」
- ④引数無し関数は「{関数名}」
尚、コード内で変数の値が変わっても、それだけでは画面に適用されません。
後述する「this.upDated({})」をやって、初めて画面に再描画されます。
style部
<style> #disp { width: 6em; } #h2_d { text-align: center; width: 3em; margin: 0 auto 0 auto; } </style>
コード内に<style></style>を設けて、そこにスタイルを書くことが出来ます。公式の説明を読むと、CSSに関しては、独自のカスタム実装があるようです。:hostのような疑似クラスを用いた スコープ付きCSSとか興味あります。このカスタムタグ内でのみ動くCSSという感じなのでしょうか?
それはさておき、今回のカウンター作成においては、各要素の表示位置やwidthを定めるだけに留めています。カウンター背景色は、html要素内へのstyle書き込みで対応しています(後述)。
スクリプト部
<script> export default { // exportは基本名前無しのdefaultで onBeforeMount (props, state) { // どこからでもアクセスできる変数「state」 this.state = { count: 0, // stateはカウンターの数値表示用 }; }, onUpdated (props, state) { // ページ更新の度に color()関数を実行 this.color(); // this を付けて関数設置 }, upDown (by) { this.state.count += by; // this.update({}) で該当要素の表示を更新 this.update({ "#h2_d" : this.state.count, }); }, color () { let hue = 255 - Math.abs(this.state.count) * 2; let rgbColor = this.state.count > 0 ? `rgb(255, ${hue}, ${hue})`: this.state.count < 0 ? `rgb(${hue}, ${hue}, 255)`: 'rgb(255, 255, 255)'; this.$("#h2_d").style.backgroundColor = rgbColor; }, reset () { this.state.count = 0; this.update({ h2_d: this.state.count, }); // this.$("セレクター") で該当要素へアクセス this.$("#h2_d").style.backgroundColor = 'rgb(255, 255, 255)'; // jQueryやUmbrellaでもやれる、以下はUmbrella /* u("#h2_d").attr({style: 'backgroundColor: rgb(255, 255, 255)'}); */ }, } </script>
内容をまとめると
export
- exportは、基本名前無しのdefaultでやるようです。
変数宣言
- 「this.変数名」とするやり方と、関数のスコープ内では「constやlet」も使えるようです。
ライフサイクルコールバック
- ライフサイクルコールバック が使えます。今回使ったのは、
- onBeforeMount () {} コンポーネントがページにマウントされた直後
- onUpdated () {} updateでコンポーネントのテンプレートが更新された直後
関数内に他の関数呼び出し
- 「this.関数B」を関数Aの中に書くことで可能です。
this.update({})で画面の再描画
- 以下の様にオブジェクトで、複数の値を一気に再描画出来る。
this.update({ 'セレクター1': 描画させたい変数1, 'セレクター2': 描画させたい変数2, })
DOM要素へのアクセス
- jQueryやUmbrellaのようなDOM要素アクセス
- this.$(‘セレクター’) 単発要素へアクセス
- this.$$(‘セレクター’) 複数要素へアクセス querySelectorAll()みたいな?
- 「this.$(“#h2_d”)」と「this.$(h2_d)」は同義っぽい?
thisってる多すぎ問題
- あっちもこっちもthis多すぎ(笑)
- this.$()でやるDOM操作は、jQueryやUmbrellaで代用してもいい
まとめ
Riot.js、案外使いやすいです。特にDOM操作に長けているjQueryやUmbrellaと併用できるのがいいですね。以前別のライブラリを試してみた時に、仮想DOM系のライブラリは、styleの適用に関して柔軟さに欠ける 感じがしたので、その点このRiot.jsはとてもよく出来ていると感じました。皆さんも興味を持ちましたら是非(笑)
今回参考にさせて頂いたサイト様
ありがとうございます。
コメント