Vue.jsでファイル選択フォームと画像プレビュー機能を作る

IT記事

Vue.jsを使ってファイル選択Formと画像のプレビュー機能を作った。以下は簡単なメモ

VueはVue cliを作ってプロジェクトを作った。

vue create nanntokaproject

CSSフレームワークとしてBootstrapを選んだ。Vue用のBootstrapプラグインBootstrapVueを使う。

https://bootstrap-vue.js.org/

BootstrapVueを入れると、例えばタブなんかは以下のように書けて楽。

div>
  <b-tabs content-class="mt-3">
    <b-tab title="First" active><p>I'm the first tab</p></b-tab>
    <b-tab title="Second"><p>I'm the second tab</p></b-tab>
    <b-tab title="Disabled" disabled><p>I'm a disabled tab!</p></b-tab>
  </b-tabs>
</div>

BootstrapVueのインストールはvue cli を使う方法が簡単だ。

vue add bootstrap-vue

ではFormを書く

<b-form @submit.stop.prevent="onGifFormSubmit" @reset="onReset">
  <b-form-file
    v-model="gifFormData.file"
    placeholder="ファイルを選択するかドロップしてください"
    drop-placeholder="Drop file here..."
    multiple
    accept=".jpg, .png, .gif"
  ></b-form-file>

  <!-- 決定ボタン -->
  <div class="d-flex flex-row justify-content-end">
    <b-button class="ml-1 mt-2" type="submit">プレビュー</b-button>
  </div>
</b-form>

BootstrapVue のファイルインプット(<b-form-file></b-formfile>)は、v-modelに指定した変数にFileオブジェクトを入れてくれる。さらにmultipleだとリストにしてくれる。便利。

では処理部分、v-modelでバインディングする変数と、呼び出す関数を書く

...  // 変数

      gifFormData: { file: [] },
      previewGifSrcList: [],

...

    onGifFormSubmit(evt) {
      this.previewGifFiles();
    },

    previewGifFiles() {
      this.gifFormData.file.forEach(fileElement => {
        const reader = new FileReader();
        reader.addEventListener("load", () => {
          // プレビュー用の変数に入れる。reader.resultはこの場合DataURLが帰る。そのままimageのsrcに突っ込めばいい
          this.previewGifSrcList.push(reader.result);
        });
        // FileReaderでFileオブジェクトを読み込む
        reader.readAsDataURL(fileElement);
      });
    }

プレビュー用の変数を用意して、FileReaderで読み込んだものを入れている。コメントで書いてあるが、imgタグのsrcに突っ込むと表示される。

ではプレビュー用の変数の中身をTemplateで表示しよう。

      <!-- gif動画プレビュー -->
      <b-card
        class="content-block"
        no-body
        v-for="(src, index) in previewGifSrcList"
        :key="index"
      >
        <div>
          <img class="img-fluid" :src="src" />
        </div>
      </b-card>

まとめ

画面に出るとテンション上がる