モミキん更新情報ブログ

パズドラのスキル検索サイト『モミキん』の情報発信ブログ

Vue.jsを使う場合と使わない場合をコードとして見比べる。

前回(3回目)の投稿から2か月も経過してしまったモミジの「スキル、なんだっけ?」の管理人ことかまぼこです。

私生活のことはさておき、前回はモミキん作成を効率的に進めることができたフレームワークVue.jsが従来のjavascriptjQueryとどう異なるか、をアバウトに説明しました。

前回の話の中で、古いjavascriptでは見た目を制御するコードを多数書く必要があり、Vueではそこから脱却できたといいましたので、今日はモミキんの検索IF部分の核部分をサンプルに具体例を示してみようかと思います。

<!-- 見た目部分のコード -->
<div id="app">
    <div v-for="(selected, index) in selects">
        <span @click="Delete(index)">[-]</span>
        <select  v-model="selected.Effect">
            <option v-for="option in Effects" v-bind:value="option.value">
                {{ option.text }}
            </option>
        </select>
    </div>
    <span>
        <input @click="Add" type="button" value="条件追加"/>
    </span>
</div>
<!-- 制御関係のコード -->
<script>
   const app = new Vue({
       el: '#app',
       data: {
               selects:[{}], // 検索条件の効果詳細情報を持つ連想配列の配列
               Effects:[ // 人様用の効果名称とDBに登録してある効果名称の変換用テーブル
                   {text:"未選択", value:null},
                   {text:"変換", value:"変換"},
                   // ...省略
               ],
           },
       methods: {
           Delete(index) {
               // 検索条件からindex番目の要素を取り除く
               this.selects.splice(index, 1); // Vueに配列内の変更を通知するためにこの記法
           },
           Add () {
               // 検索条件を新たに追加する
               this.selects.push({});
           },
       }
   };
</script>

上記のコードは、検索項目を足したり減らしたりするための実際のコードです。 記憶が確かなら、IF部分の出だしはこんなところから始まったはずです。(git管理し始めたのだいぶ後なので詳細なログがない!!)

<div v-for="(selected, index) in selects" >

一番に感動したのはこの部分です。 v-forという属性に xxx in yyyという値を入れることで、Vueのdata要素で定義したyyyという配列の中身をxxxとして展開してくれます。カッコ書きで(selected, index)と書くことで何番目の要素であるかもindexに覚えててくれます。

これで、app.data.selectsにデータを足したり(Add関数)削除する(Delete関数)だけで、検索項目を増減させられます。

次のコードで、selectes配列内の各連想配列にデータをセットする方法ですが、これは以下のようなコードで実装されています。

<select  v-model="selected.Effect">
    <option v-for="option in Effects" v-bind:value="option.value">
        {{ option.text }}
    </option>
</select>

v-model="selected.Effect"と言うのが、select要素のvalueとselected.Effectに紐づけてくれます。 select要素内のoptionリストの生成は先ほどと同様v-forに配列を渡すことでできます。

Vueを使って最も感動をしたのは、v-forやv-bindみたいにHTMLからJavascript内の変数を呼び出したり紐づけたりできることです。 昔のjavascriptjQueryでこれはできませんでした。

もし、最初のコードを古い書き方をすると(あくまでイメージですが)下記のようになると思います。

<div>
    <div id="検索条件">
        <!-- N個目の検索条件の詳細を記述するためのHTMLをここに書けない -->
        <!-- 今、検索条件がいくつあるのかを知っているのはjavascriptだけであり、HTMLはjavascriptが持つ変数を関知しないから -->
    </div>
    <span>
        <input click="Add" type="button" value="条件追加"/>
    </span>
</div>
<script>
   // わずかでも簡略化するため(うろ覚えな)jQuery(的)な書き方で
   let selects = []; // 検索条件の効果詳細情報を持つ連想配列の配列
   let Effects:[ {}, {} ];  // 人様用の効果名称とDBに登録してある効果名称の変換用テーブル
   const form = $("#検索条件");

   fuction WriteSelects() {
       let div = $("<div>");
       for (let i = 0; i < selects.length; i++) {
           let selected = $("<div>");
           selected.append($("<input>", { click:"Delete(" + i + ")", text:"[-]" } ));
           const list = EffectSelectList(i);
           // listの初期選択値をselects[i].Effectとなるようにする処理をここに書く
           selected.append(list);
           div.append(selected);
       }
       form.html(div.html());
   }
   function Add() {
       selects.push({});
       WriteSelects();
   }

   function Delete(index) {
       selects.splice(index, 1);
       WriteSelects();
   }
   function EffecSelectList(index) {
       const id = "Effect" + index;
       const change= "ChangeEffect(" + index + ")";
       let options = $("<select>", {change:change, id: id}); // 選択要素が変わったときにJavascriptに通知するように変更時呼び出される関数を(この要素だと特定できる引数と合わせて)定義する
       for (let i = 0; i < Effects.length; i++) {
           options.append($("<option>", {value:Effects[i].value, text:Effects[i].text}));
       }
   }
   function ChangeEffect (index) {
       selects[index].Effect = $("#Effect" + index).value;
   }
</script>

ざっくりVue.jsではJS部分が20~25行程度、古い書き方では(関数を一部省略してなお)35~40行程度となりました。 古い書き方の一番面倒なところは、WriteSelectsとEffecSelectListのようにHTMLを記述するJavascriptがあるところです。さらにこの構造を複雑にする要因に、JavascriptでHTMLを書き、そのHTMLからJavascriptを呼び出すための属性を付与していることも挙げられます。

古いJavascriptとVue.jsのコードを比べると、共通のロジックはAdd()とDelete()と配列宣言部だけであることと、Vue.jsではVue関連の宣言を除くと共通部しかないことがわかります。

一方、Vue.js側のHTML部分は15行程度、古いJavascriptでは7行程度とHTMLは古い書き方の方が一見短くシンプルに見えます。 しかし前回の記事でも説明したように古い書き方ではJavascript内にHTMLを記述するコードが多くなり、今回で言えばそれは(35 - 20 = )15行程度あることが分かります。

コードの総量的な意味でもVue.jsに軍配が上がりますがそれ以上に、見た目的な話をJavascript内に持ち込まざるを得ない古い書き方ではHTMLを見てもどんなサイトなのか想像することができません。

仮想DOMも考えると描画速度のメリットもVue.jsにはあるような気はしますが、直接比較したことないのでそんな気がするよ程度で。

最後に、Vue.jsの良い点を再三になる部分もありますがまとめますと、

  • Javascript内にHTMLを書かなくて済む
  • 上記のおかげで、Javascriptを呼ぶHTMLをJavascriptで書く、ということがなくなる
  • 見た目の記述はすべてHTMLやCSS、利用データ部分はdata部、ロジック部はmethodos、computed部に切り分けられる
  • 複雑な構造になるほど記述量が古い書き方より少なく済む
  • 描画速度が多分速い

なんてことが言えるかなと思います。 こんな良いところ(悪いところでも)があるよ! という話があればぜひ教えてください。

ではでは~。

古いjavascriptからの脱却。

どうも、モミジの「スキル、なんだっけ?」の管理人ことかまぼこです。 開始2日目にして既に何を書くか思いつかなかったダメ執筆者です。 (無理に書くものでもないですが)

モミキんの構成要素の中で大きな役割を占めているものについて考えた結果、Vue.jsとService workerの2つかなと思ったので、今回はVueについて思ったことを書いていこうと思います。

Vue.jsとはMVVM的にHTMLとjavascript(ロジック)を結びつけるためのフレームワークと呼べばいいのでしょうか。(実はMVVMがどういうものかよく分かっていない民)

MVVMについて詳しく語れない身ですがVue.jsを使う上で自分が感じたのは、ロジックを主体にしてコードを書きやすい、ということです。 (プログラムを書いたことがない人だと想像しにくいかもしれません。。)

かつて引きこもり時代に、jQueryを多用した自分用ツールやウェブサイトを作ったことがあるのですが、この時、ある問題に陥っていました。 作ったサイトは言ってしまえば単に、動画像をアップロードするとタグ情報に応じて分類し、表示するだけのものだったのですが、一覧ページを作るためのロジック、div内に要素を並べるロジックなど、見た目を制御するロジックが大量にあり、プログラミングと言いつつ、その実HTMLを生成するスクリプトを書いている気分でした。

一方、Vueを利用したモミキんでは見た目を制御するロジックは、文字サイズのシークバーによる変更とモンスター一覧の幅を自動計算する部分だけです。(これも元々はCSSで解決していましたが、競合する設定を回避するためにjsで対応しました) 他の見た目に関する設定はすべてHTMLとCSSに一任されています。 このため、ロジック側は単にデータを配列やオブジェクトに格納するだけで良くなり、見た目とロジックを同時に考えさせられる苦痛から解放されました。

Vueである必然性はないかもしれませんが、素のjavascriptjQueryによるHTMLの改造から脱却できたのはとてもいい経験でした。 今回はこの辺りでおしまい。Service workerについてはまたそのうち。

モミキんのデータ構造

かまぼことかそんな名前の者です。

パズドラの絞り込み型スキル検索サイトモミジの「スキル、なんだっけ?」を作り始めるにあたり何よりも必要だったのが、どういうデータ構造にするか? という問題を解決することでした。

効果詳細の例

持続ターンや倍率、変換対象などの詳細で絞り込みをしたい以上、それらのデータを削る事は絶対できないわけですが、じゃあどんな項目を用意すれば全てのスキル効果を表現できるのかがぱっと想像できませんでした。

例えば、ブレススキルでは自身の攻撃力にN倍するもの、ランダムにN~M倍するもの、攻撃力とは無関係にXダメージ与えるもの、PTの属性火力を合算してN倍するもの、ブレス属性が指定されているもの、自身の主属性と同一の属性攻撃をするもの、単体相手のもの、全体相手のもの、特定属性の相手のみのもの…

色々な条件があり、正直いまだにどうまとめると本当に絞り込みたいデータを得られるのか分かっていない部分が多いです。

現状の構造

現在のスキル効果のデータ構造は結局以下のように落ち着きました。

  • 効果名
  • 持続ターン
  • 対象ドロップ(ただし生成スキルについては除外対象)
  • 生成ドロップ
  • ベース火力
  • ブレス属性
  • 倍率1
  • 倍率2
  • 定量1
  • 定量2
  • 対象タイプ
  • 対象属性
  • 対象覚醒
  • 位置

現在(2019/11/2)のところこの表現で記述できないのは、ランダム発生スキルと変身スキルの変身先と固定形生成の厳密な生成位置や向きですかね。。(ランダム発生スキルは周回やランダンで利用するスキルでもないのでいいかと妥協しています

全部網羅的に説明するのは大変なのでちょっと分かりづらそうなところだけピックアップします。

  • 対象ドロップ:変換の変換元や目覚め、ドロップ強化などで効果を加えられるドロップを指定しています。例えば全ドロップを強化という文脈では対象ドロップは回復含む6色を記述し、全ドロップをロックという文脈では妨害系ドロップを含む10色を記述しています。
  • ベース火力:ブレス系スキルで倍率がかかる元となる源を指定します。自身の攻撃力であればSelf、PTの属性攻撃力であれば属性、PTのHPであればHPなどの指定をしています。また即時回復で自身やPT回復力依存の場合もここで指定しています。
  • 倍率、固定量の1,2:これは基本的にランダムや恨みなどの効果量に幅があるものの指定に利用しています。通常は1だけ埋めて2に同じ値を挿入しています。例外的に固定ダメージを複数回飛ばすものだけ、固定量1に固定ダメージ量、2に回数としています。(実はここの検索をいい感じにする方法は現状、未実装です。。)サイトでの検索では最小倍率、最大倍率、最小固定量、最大固定量、という名前に置き換わっています。これのおかげで最小倍率 <= 倍率1かつ倍率2 <=最大倍率のレンジ検索ができるようになっています。
  • 位置:当初は列生成の位置を指定するために用意したものでしたが、正方形生成やL字生成、果ては4隅生成とかいう謎生成の生成位置にまで使いました。列生成においては基本的に65盤面での生成位置を上下左右からN列目を例えば上N、下N、左N、右Nで表現しています。正方形などはもう少し自由な記述で左下とか右上とかそんな記述になっています。(厳密でシンプルな記法募集中)

この記事を書いていて、ブレスの対象も項目に加えればスキル効果を減らせるし検索もしやすくなるんじゃないかってふと思いました。変えようかな。

兎にも角にも、現状のデータ構造(効果詳細部)についての簡単な説明でした。

パズドラスキル検索サイトの開設

初めましての人は初めまして。そうでない人は毎度お世話になっております。

パズドラの絞り込み型スキル検索サイトモミジの「スキル、なんだっけ?」(モミキん)を開発とかをしているかまぼことかそんな名前の者です。

モミキんを作ろうと思ったきっかけ

パズドラのスキル検索ツールって探せばないわけではないのですが、例えば複合スキルを調べるだとか、短いターン数のものを絞り込むだとか、変換対象の色を絞り込むとか、そういうことを細かく全部指定できるツールって(僕が知る限り)なかったんですよね。あったら更新面倒くさいので閉鎖するかもしれません(笑)

嘘です、手伝ってくれた人のためにも当面は続けます。

欲しいものがあるなら作ればいいじゃない、と過去に何度か考えたこともあったのですが、表記ブレや強化倍率の記述が曖昧なスキル効果をどうまとめるかとか、(2019/11/2現在)2000ちょっとあるスキル効果入力作業をどうするかとか、一時期の素材スキル変更ループの存在を考えてたらなかなか動きだせなかったんです。

でも某オープンチャットのグループであったらいいよねーみたいな話を出してみたら同じように感じてるユーザーがいると分かってやっぱり作ろうってとっかかり始めました。

このサイトの目的

宣伝といいますか、より多くの人に便利に使ってもらってよりよい改善の意見などを集められたらいいなという感じです。

人に相談した結果、やはり検索にひっかかかって入口となるランディングサイトを設けるのが良いと言われたのでその足掛かりになればと。

あ、ちなみに広告等は当面設置予定はないので、人が増えても僕の収入は増えません(泣)

今後の記事の内容

僕としては、モミキんアップデート情報を載せたり、実装をどんな風にしてるかとかの紹介なんかをできたらいいなと思っています。

パズドラの話もできたら楽しい気がしますが、如何せん僕はにわかパズドラーなので炎上させそうで怖い。。

ちなみに実装などの話をする都度に言うと思いますが、本職プログラマーとかではないのでコードのクオリティは残念なものです。命名規則とか拘ると英語が分からなくてコードを書けなくなる病気です。