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

IT記事

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

まずVue cliを作ってプロジェクトを作る。

vue create nanntokaproject

UIフレームワークを使うと楽に書ける。今回はBootstrapVueを使うことにした。

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

vue cli を使うとインストールも簡単だ。

vue add bootstrap-vue

選択ファイルが一つの場合

まずb-form-fileを書く

            <b-form-file
              v-model="form.file"
              placeholder="ファイルを選択するかドロップ"
              drop-placeholder="Drop file here..."
              accept=".jpeg, .jpg, .png"
              @input="onInputFile"
            />

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

あと@inputでファイル選択時イベントに関数をアタッチしている。

次はその関数と変数達

  // フォーム用変数
  form = {
    file: new File([""],"")
  };

  // プレビュー用の変数
  previewSrc = null;

...

  // ファイル選択時にプレビュー用のsrcを生成
  onInputFile() {
    const reader = new FileReader();
    reader.addEventListener("load", () => {
      this.previewSrc = reader.result;
    });
    reader.readAsDataURL(this.form.file);
  }

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

              <img
                class="avatar_img rounded-circle mb-3"
                :src="previewSrc"
              />

これでファイルを選択した時に画面にプレビューされる。

複数ファイルある場合

次は複数ファイルの場合。プレビューボタンがあるバージョン。

<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>

...  // 変数

      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);
      });
    }
      <!-- 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>

まとめ

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