天然パーマです。

Vue.jsでメロディー・雛・マークスを出す

今回はVue.jsでメロディー・雛・マークスを出してみる。 Vue.jsは前にもいじったことがあるけど、ブランクがあるので、とりあえずやる。 これまでのメロディー・雛・マークスは以下。

Vue.jsはCDNで読み込ませる。他にもDMM APIをコールるすためにaxiosというライブラリを、 また、いちおカッコつかえるためにBootstrapを使ったので、それらもCDN経由で。

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
...
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.1/axios.min.js"></script>

こいつを書いたindex.htmlをローカルで作り、app.jsにJSを記載する。 file://.../index.htmlをブラウザで閲覧するのでAjaxの制限に引っかからずにAPIを叩けるし、 APIキーを人に見られることはない。

公開するにはそれなりに準備が必要だけど、今回の場合は CDNを活用してローカルで動かすのがいいだろう。 これで、メロディー・雛・マークスを出すことに専念できる。

アプリではこの4つのプロパティを使う。

data: {
    keyword: null, // 女優検索に使用するキーワード
    stars: null, // 女優情報を配列で格納する
    loading: false, // ローディングかどうか
    errored: false // エラーが発生したらtrue
}

Vue.jsではこれらのプロパティ(モデル)はDOM上のものとJSで書いているアプリアプリケーションで 完全に関連付けられていて、リアクティブになっている。例えば、jQueryの典型的なやり方だと、 Ajaxでデータを持ってきたら、それを元にデータを整形しhtml()とかtext()とかで指定したDOMを書き換える なんてことをやるが、Vue.jsならこうした作業がいらない。 ある意味ViewとModelを切り離す、みたいなことになる (実際、Vue.jsを初めて触った時、Webフレームワークにおけるテンプレートエンジンの活用、っぽいなと思った)。

なので、

<input v-model="keyword" type="text"
       placeholder="キーワードを入れてね">

と、v-model属性の値としてkeywordを指定すれば、 テキストフォームに入力した値はJS上からkeywordのプロパティ値として参照可能。 他にもJS側でAjaxが成功したらレスポンスの中身をとってきて、 AV女優情報の配列をstarsに入れれば、それが即反映されHTML内に記載した通りに描画される。 実際には、v-ifv-elseなどのタグを利用してローディング中ならスピナーを表示、 ロードが終わったら検索結果一覧を表示、というように制御している。

検索ボタンを押すと発火されるgetStarsメソッドはこんな具合。

getStars: function() {
    // ローディング中を表す
    this.loading = true;
    axios
        .get('https://api.dmm.com/affiliate/v3/ActressSearch', {
            params: {
                api_id: api_id,
                affiliate_id: affiliate_id,
                hits: 50,
                // フォームに入力された検索語を参照
                keyword: this.keyword
            }
        })
        .then(response => {
             // レスポンスを元にAV女優情報をstarsに入れる
             this.stars = response.data.result.actress
         })
         .catch(error => {
             console.log(error)
             // エラーだったら
             this.errored = true
         })
         // 処理が終わったらローディング状態を解除
        .finally(() => this.loading = false)
}

AV女優一覧を表現するstarsを描画するHTML部分はこうだ。

<div v-for="star in stars"
     class="col-sm-2">
  <div class="card mb-4 text-center">
    <img v-bind:src="star.imageURL ? star.imageURL.large : 'dummy.gif'"
         class="card-img-top" />
    <div class="card-body">
      <div class="card-title">{{ star.name }}</div>
      <div class="card-sub-title text-muted">{{ star.ruby }}</div>
    </div>
  </div>
</div>

ネストが深くなっちゃってるので分かりにくいが、 v-for="star in stars"で個々の要素をstarに入れて、 {{ star.name }}で女優名を表示したりしている。

さて、こうして完成。試しに検索してみる。

おっ、深田えいみ出てきた! けど、イメージ写真がない女優さんが結構いる。

で、いよいよメロディー・雛・マークスを出す。

出た!右はじにメロディー・雛・マークス!写真がないのが残念!

そして手持ち無沙汰になった僕は、指が勝手に動いてなぜか「ちんこ」と検索していた。

えっ、望月珍子さん!!