2019.12.04 - Article

Riot.jsで作った消費税計算ツールとRiot v3の好きな所

Tag:

これはRiot.js Advent Calendar 2019の4日目の記事です。

Riot.jsVue.jsがGitHubスター1万程の時は同じぐらいの知名度だったと思いますが、今では大きく差をつけられアドベントカレンダーも空きが目立つので(涙)、少しでも布教になればと書かせてもらいました。

しかしながら僕が好きなのはv3時代のRiotです。
最新版はv4ですが、v4になって制約が多くなりriot特有のメリットが薄れたと思うのでv3のまま使っています。

制作物


タックス | 消費税計算ツール

Riot.jsはツール的なもの作る時とても便利ですね。
v3でriotを使いたい時の参考にして下さい。
cssは無視しています。

index.html

<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>tax</title>
<script src="riot+compiler.min.js"></script>
<script type="riot/tag" src="tag.html"></script>
</head>
<body>
<div data-is="riot-main"></div>
<script>
riot.settings.autoUpdate = false;
riot.compile(function(){
  riot.mount('*');
});
</script>
</body>
</html>

 

tag.html

<riot-main>
  <div class="theme_light">
    <div class="re_container st_form_light re_pv_5">

      <div data-is="riot-calc" mode="in"></div>
      <div data-is="riot-calc" mode="out"></div>

    </div>
    
  </div>
</riot-main>

<riot-calc>
  <div class="re_row_2 re_pv_5">
    <div class="re_col_lg_3">
      <div><span class="title3">税抜</span></div>
      <div><input class="st_form_input" type="text" readonly="{mode==='out'}" onkeyup="{ehTypeIn}" ref="input_out"/></div>
    </div>
    <div class="re_col_lg_3">
      <div><span class="title3">税</span></div>
      <div><input class="st_form_input" type="text" readonly ref="input_tax"/></div>
    </div>
    <div class="re_col_lg_3 re_pb_4">
      <div><span class="title3">税込</span></div>
      <div><input class="st_form_input" type="text" readonly="{mode==='in'}" onkeyup="{ehTypeOut}" ref="input_in"/></div>
    </div>
    <div class="re_col_lg_3">
      <div>
        <div class="st_form_group">
          <span class="st_form_addon">税</span>
          <select class="st_form_input" onchange="{ehChangTax}">
            <option each="{val in optionListTax}" value="{val}" selected="{val===optionTax}">{val}%</option>
          </select>
        </div>
      </div>
      <div class="re_pt_1">
        <div class="st_form_group">
          <span class="st_form_addon">端数</span>
          <select class="st_form_input" onchange="{ehChangPoint}">
            <option each="{val in optionListPoint}" value="{val}" selected="{val===optionPoint}">{val}</option>
          </select>
        </div>
      </div>
    </div>
  </div>
  <script>
    var tag = this;
    tag.mode = tag.opts.mode;

    tag.optionListTax = ['3', '5', '8', '10'];
    tag.optionListPoint = ['切り捨て', '切り上げ', '四捨五入', 'そのまま'];

    tag.optionTax = tag.optionListTax[2];
    tag.optionPoint = tag.mode==='in' ? tag.optionListPoint[0] : tag.optionListPoint[1];

    
    tag.ehTypeIn = function(e){
      tag.refs.input_out.value = e.target.value.replace(/[^0-9.]/g, '');
      inputUpdate();
    };

    tag.ehTypeOut = function(e){
      tag.refs.input_in.value = e.target.value.replace(/[^0-9.]/g, '');
      inputUpdate();
    };
    
    tag.ehChangTax = function(e){
      tag.optionTax = e.target.value;
      inputUpdate();
//			tag.update();
    };

    tag.ehChangPoint = function(e){
      tag.optionPoint = e.target.value;
      inputUpdate();
//			tag.update();
    };
    
    function inputUpdate(){
      var val, tax;
      //税込を求める
      if(tag.mode==='in'){
        if(tag.refs.input_out.value==='') return;
        val = tag.refs.input_out.value;
        tax = val * tag.optionTax / 100;
        if(tag.optionPoint==='切り捨て'){tag.refs.input_tax.value = Math.floor(tax);}
        if(tag.optionPoint==='切り上げ'){tag.refs.input_tax.value = Math.ceil(tax);}
        if(tag.optionPoint==='四捨五入'){tag.refs.input_tax.value = Math.round(tax);}
        if(tag.optionPoint==='そのまま'){tag.refs.input_tax.value = tax;}
        tag.refs.input_in.value = tag.refs.input_out.value * 1 + tag.refs.input_tax.value * 1;
      }
      //税抜を求める
      if(tag.mode==='out'){
        if(tag.refs.input_in.value==='') return;
        val = tag.refs.input_in.value;
        tax = tag.refs.input_in.value - val / (1 + tag.optionTax / 100);
        if(tag.optionPoint==='切り捨て'){tag.refs.input_tax.value = Math.floor(tax);}
        if(tag.optionPoint==='切り上げ'){tag.refs.input_tax.value = Math.ceil(tax);}
        if(tag.optionPoint==='四捨五入'){tag.refs.input_tax.value = Math.round(tax);}
        if(tag.optionPoint==='そのまま'){tag.refs.input_tax.value = tax;}
        tag.refs.input_out.value = tag.refs.input_in.value - tag.refs.input_tax.value;
      }
    }
    
  </script>
</riot-calc>

Riot v3 こうすると使いやすい

Riot.js v3は自由に書けるのですが使っていく内にある程度ルールを決めたほうが使いやすくなりました。
そうとう意識の低い使い方ですがとてもコードを書くのが楽しいです。
上記のコードも基本的にこの規則に従っています。

1. settings.autoUpdateをfalseにして自動でタグが更新されるのを防ぐ
理由:自動でupdateするとパフォーマンスが悪いので手動でupdateするようにします。

2. タグ内でまずvar tag = this;を定義してインスタンスはtagという変数で扱う
理由:thisだと呼び出し元によって対象が変わるため

3. onclickなどのイベントにバインドする関数(イベントハンドラは)の名前はehではじめる
理由:イベントハンドラ(eh)用の関数とわからなくなるから

4. riot-mainというタグを作り、その中で各種タグを読み込みifディレクティブで調整する
理由:最初のみmountメソッドを使えば、以降はデータに応じで自動でmount, unmountしてくれる

5. tagファイルの拡張子を.htmlにする
理由:エディタでhtml, js, cssのシンタックスハイライトがきちんと動作する

6. 1アプリケーション1ファイルで複数あるタグもまとめて書く
理由:処理を探すのが楽

7. タグの事前コンパイルはせずにブラウザでコンパイルする
理由:ビルドツールが不要なので気軽に書ける

8. タグ名はriot-で始める
理由:Riotによって作成されたタグだとわかりやすい

9. タグはdata-is属性でマウントする
理由:spanやliやtdなどで使えるので意図したレイアウトにしやすい

他にも作ってます

他にも各種サービス・ツールをRiot.jsを使って作っています。
ウェブゴトのサービス

RIOT! RIOT! RIOT!

コメントを残す