input要素を使って選択した画像ファイルを即座にブラウザ上にプレビューとして表示させてみたい思ったことはありませんか?そんな人のために本文書を作成しました。

vue.jsの準備

vue.jsを利用しますが、特別な環境を構築することなくvue.jsの動作確認を行うことができるcdnを利用します。


<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Image Preview</title>
  </head>
  <body>
    <div id="app">
      <h1>{{ message }}</h1>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
    <script>
     new Vue({
        el: "#app",
        data() {
          return {
            message:"Try Preview!"
          }
        },
      })
    </script>
  </body>
</html>

ブラウザ上に大きな文字でTry Preview!と表示されたらvue.jsの準備は完了です。

画面上にtry preview!が表示
画面上にtry preview!が表示

input要素の設置

ファイルを選択するinput要素を追加しましょう。ファイルを選択するのtypeはfileを設定してください。


<h1>{{ message }}</h1>
<div>
  <input type="file">
</div>

ブラウザにはファイルを選択ボタンが表示されます。ファイル選択ボタンをクリックするとファイル選択画面が表示されます。

アップロードファイル選択画面
アップロードファイル選択画面

input要素へのrefを使ったアクセス

input要素で選択したファイル情報を取得するためにvue.jsの属性refを利用します。refを利用するとvue.jsからref属性を設定した要素にアクセスすることができます。


<h1>{{ message }}</h1>
<div>
  <input type="file" ref="preview">
</div>

vue.jsからはthis.$refsを使ってアクセスすることができます。refに設定した値と$refsを利用することでrefを設定した要素の情報を取得することができます。


this.$refs.preview

本当にinput要素にアクセスできているか知りたい場合はライフサイクルフィックの中でconsole.logを使って確かめてみましょう。input要素が表示されるはずです。


mounted(){
  console.log(this.$refs.preview)
}
// 結果(ブラウザのコンソール)
<input type="file">

ファイル情報の取得

changeイベントを利用してinput要素で選択したファイルの情報を取得します。changeイベントではuploadFileメソッドを実行します。


<input type="file" ref="preview" @change="uploadFile">

vue.jsにuploadFileメソッドを追加します。


methods:{
  uploadFile(){
    console.log(this.$refs.preview.files[0])
  }
}

profile.pngというファイルを選択していますがブラウザを見るとthis.$refs.preview.files[0]にファイルの情報が入っていることが確認できます。

ファイル情報を取得
ファイル情報を取得

createObjectURL

取得したファイル情報をcreateObjectURLの引数に入れることでファイルにアクセス可能なURLを作成することができます。作成したURLを使って画像のプレビューを表示することができます。作成したURLは一時的にブラウザに保存されるものです。

作成したURLを保存するデータプロパティurlを追加します。


data() {
  return {
    message:"Try Preview!",
    url:""
  }
},
methods:{
  uploadFile(){
      const file = this.$refs.preview.files[0];
      this.url = URL.createObjectURL(file)
  }
}

これでプレビュー画像を表示するための準備は完了です。

プレビュー画像の表示

imgタグを使って、crateObjectURLで作成したURLをsrc属性に設定します。v-ifを利用してurlに値が入っている場合のみ表示を行います。


<div v-if="url">
  <img :src="url">
</div>

ファイルを選択した瞬間にプレビュー画像が表示されます。実際に利用する場合はプレビューの画像の大きさ、場所を調整してください。

画像のプレビューが表示
画像のプレビューが表示

開発ツールでプレビューの要素を確認すると以下のように表示されます。


<img src="blob:null/1dc129b3-f5ff-4eb5-ad49-7ecc9dbb5ef4">

プレビュー画像を非表示に

表示したプレビュー画像を非表示にしたい場合でもvue.jsを利用すれば簡単に実現できます。


<div v-if="url" style="position:relative">
  <div style="position:absolute" @click="deletePreview">X</div>
  <img :src="url">
</div>

styleのpositionを利用して、プレビュー画像の左上に”X”ボタンを追加します。追加したXボタンをクリックするとプレビューが非表示になるようにdeletePreviewメソッドを追加します。


deletePreview(){
  this.url = '';
}

プレビューの左上にある”X”をクリックするとプレビューは非表示になります。

非表示用のXボタンを追加
非表示用のXボタンを追加

非表示にする際には、作成したURLを開放するためにrevokeObjectURLを実行しておきます。


deletePreview(){
  this.url = '';
 URL.revokeObjectURL(this.url);
}

2回目の選択でプレビューされない

一度プレビューで表示した画像を非表示し、再度同じ画像を選択するとプレビューが表示されません。

別の画像だとプレビューは表示されます。
fukidashi

この問題を避けるためには選択したファイルの値を削除する必要があります。


uploadFile(){
    const file = this.$refs.preview.files[0];
    this.url = URL.createObjectURL(file);
    this.$refs.preview.value = "";
},

削除後に同じファイルを選択してもプレビューは表示されます。

vue.jsを利用することは必須ではありませんが、プレビューを実行してみたい場合はぜひ使ってみてください。