2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

昔を知らない初級者が、Riot.js v9をいじってみる

Last updated at Posted at 2024-04-03

はじめに(読み飛ばしOK)

こんにちは。
プログラム及び、JavaScript初級者です。
ネットを色々と漁っていたら、ライブラリというものの存在を知りました。
ライブラリには沢山の種類があようです。どれか面白そうなものは無いか?見ていたら、カスタムタグというのを使用する、Riot.js を見つけました。

Riot.js の記事をQiitaで検索しても最近の記事はあまり見つけられず、人気や使用頻度なども下火なのかな?とも思いました。
使い方の記事も少な目で大変そうなのですが、公式ページは日本語表示もあり、とっつきやすさはあると思いました。練習がてら少しいじってみようと思います。

尚、「Hello world」の表示に関しては、チュートリアルって事で先に済ませてあります。

作ったもの log_list

作ったものは、テキストエリアに打ち込んだ文字がlogとしてlist状に下へ打ち出されていくものになります。色々盛り込んでみようとも思い、見た目掲示板風にしてみました。意識的に組み込んでみたものは、以下の様になります。

  • 別のjsファイルをimportし、propsにマウント
  • Riot.jsのバージョン取得と表示

log_list_01.png

作成したファイル

  • index.html コンポーネントのマウントを司る
  • log_list.riot カスタムタグのファイル、拡張子は.riot
  • id.js props用
  • style.css スタイルシート

index.html (<body>)

<body>
  <!-- カスタムタグの表示位置-->
  <log_list />

  <!-- <log_list/> は外部ファイルで指定 -->
  <script src="./log_list.riot" type="riot"></script>
  
  <!-- cdnで riot.js とコンパイラ -->
  <script src="https://unpkg.com/riot@9/riot+compiler.min.js"></script>
  
  <!-- コンパイルとマウント、他import -->
  <script type="module">
          import {id} from "./id.js" // 別jsファイルをimport

    (async function main() {
      await riot.compile();

      riot.mount('log_list', {
          title: 'log_list ',
          ver: ` @ riot.js ${riot.version}`, // バージョン取得
          id: id, //importした別jsファイルをpropsとしてマウント
      })
    }())
  
  </script>

</body>

Riot.jsの昔の記事を見ると、V3かV4の辺りで大きな書式変更があったらしいです。その後、細かい変更などを経て、今(2024 4月現在)ではv9となりました。尚、{riot.version} で常にその時に読み込まれているバージョンを取得し、表示させています。便利です。

log_list.riot(カスタムタグ名 log_list)

<log_list>
    <div id="display">
        <h1>{ props.title }<span>{ props.ver }</span></h1>
        <textarea id="textarea" placeholder="{props.id.textarea.placeholder}"></textarea>
        <br> 
        <button id="add" onclick="{addText}">{ props.id.add.value }</button>
        <br>
        <br> 
        <div id="below">{ props.id.below.value }</div>
        <hr>

        <!--this.update({}) で更新される個所 -->
        <!--each による配列のループ処理 -->
        <div each="{item in state.logs}">
            <!--三項演算子でclass設定 new表示用 -->
            <span class="{item.index == state.logs.length ? 'newest': ''}">{ item.date }</span>          
            <div class="container">
                <div>
                    { item.index }.&nbsp;
                </div>
                <div class="indent">
                    { item.text }
                </div>
            </div>
            <hr>
        </div>
    </div>

    <script>
        export default {
            /*---マウント前に1回実行、state設定 ---*/
            onBeforeMount(props, state) {
                this.state = {
                    logs: [],
                    index: 0,
                }
            },
            
            /*---onclickで呼ばれる関数 ---*/
            addText() {
                if (this.$("#textarea").value != '') {
                    this.state.logs.unshift({
                        index: this.state.logs.length + 1,
                        date:  this.date(new Date()), // this を付けて別関数呼び出し
                        text: this.$("#textarea").value, // this.$("セレクター")で、要素へアクセス
                    });
                
                    this.$("#textarea").value = '';

                    this.update ({ //state内容が画面に適用される
                        logs : this.state.logs,
                    })
                }
            },
            
            /*---日付表示作成用関数 ---*/
            date (d) {
                const week = ["", "", "", "", "", "", ""];
                return (
                    String(d).replace(
                        /^.*(\d{4})\s(\d{2}:\d{2}:\d{2}).*$/, 
                        `$1/${d.getMonth() + 1}/${d.getDate()} (${week[d.getDay()]}) $2`
                    )
                )
            },
        }
    </script>
</log_list>

日付表示やら何やらで、長くなってしまいました。
主な留意点としては、this.update({})をやってあげないと、stateの変更内容が画面表示に適用されない ところでしょうか?

id.js(お試し)

export const id = {
    textarea: {
        placeholder: 'Please text here...'
    },

    add: {
        value: 'Add',
    },

    below: {
        value: '▼ Below here is the log'
    },

}

この程度のコードでこういった外部ファイルは本当は必要でもないんですが、お試しで作ってみました。

ただ、こういった 外部ファイルの importやexport の方法がよく分からず、しょうがないので、index.htmlでimportし、props経由でデータの取得がたまたまうまくいったので、こういう方法を取ってみました。
正直、これであっているのか?

style.css

span {
    font-size: small;
}

#display {
    width: 400px;
}

#textarea {
    width: 100%;
    height: 100px;
    resize: none;
}

::placeholder {
    color: darkgray;
}

.newest::after {
    content: ' new !';
    color: red;
}

.container {
    display: flex;
}

.indent {
    white-space: pre-wrap;
}

特にどうってことのないCSSです。
log_list.riotファイルの中に<style></style>を設けて記述しても良かったんですが…
もしかしたらCSSや上記のJSファイルなど、拡張子.riot のファイル1つにまとめるのが本来の目的なのかもしれません?

まとめ Riot.js を使って見た感想

  • 思ったよりも使いやすい
  • 学習量は、多くないと思う
  • this が多すぎ(笑)
  • this.$("セレクター")は、jQueryやUmbrellaで代用しても良さそう
  • onBeforeUpdate(props, state) {
      //更新前にコンテキストデータの再計算が許可されている
    }
    onUpdated(props, state) {
      // update が呼び出され、コンポーネントのテンプレートが更新された直後
    }
    この辺りのライフサイクルに柔軟性を感じさせる
  • 別jsファイルなどのimport方法がこれであってるのか分からないというか、拡張子.riot のファイル1つにまとめるのが本来の目的なのかもしれません? よく分かりません…

以上、Javascriptのライブラリ、Riot.jsを使って見た感想でした。

今後いじってみたいもの

  • Node.js とか?
  • Svelte とか?

参考サイト様

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?