Vuejsでの画像ファイルアップロード

2018-08-19 #javascript  #vue.js 

Vue.jsを使った画像ファイルアップロードのサンプルを書いてみたのでメモ

リポジトリ github.com/seihmd/vue-image-upload

実際の動作 https://seihmd.github.io/vue-image-upload/

アップロードまでのフロー

  1. 画像ファイルを選択
  2. プレビューを表示
  3. キャンセル(選択を削除) or アップロード実行

なぜ作ったのか

ファイルアップロードを行うjsライブラリやVueコンポーネントライブラリ、HowTo記事はもちろん存在する。

ただこれらはいずれも画像選択して即アップロードを行うようになっているので上記の実現したいフローとは異なる。またdropzoneは汎用的すぎてメンテナンス、カスタマイズがしづらい印象があった。

技術的なメモ

<input type=“file”>の挙動

正直知らなかったがtype=“file”のinputタグはそのままでドラッグアンドドロップに対応している。

<input type="file"/>

このボタン上にファイルをドラッグすれば選択状態になってくれる。

このボタンを消して高さと幅を与えてやればよくある画像選択UIの原型ができる。デフォルトの見た目がボタンなので高さと幅を設定する発想がこれまでなかった。

<style>
  .container {border: 1px solid black; width: 100px; height: 100px;}
  .input-file {opacity: 0; width: 100%; height: 100%; cursor: pointer;}
</style>

<div class="container">
  <input type="file" class="input-file">
</div>

選択を削除する

画像を選択した後、cancelをクリックしたら選択を削除する必要がある。 ここで出されているアイデアを参考にinputを再レンダリングして初期化する方法を採っている。

https://github.com/seihmd/vue-image-upload/blob/master/src/ImageUpload.vue#L67

<input v-if="!mustReset">
methods: {
  // ...
  reset() {
    // ...
    this.mustReset = true;
    this.$nextTick(() => {
      this.mustReset = false;
    });    
  }
}

他にもinputエレメントのtype属性を’text’にして’file’に戻すという手もあるようだが(試してない)、こちらの方がブラウザの差異を気にしなくてよさそうだと考えた。