図書館合金 Part 2

programming and books, music etc.

vue.js で複数ファイルアップロード、プレビュー表示

画像を登録してファイルアップロードという処理だが、登録画面からファイル一個だけ登録すればいい、という話はあまりなくて、なんだかんだで複数登録したいんだがどうすればいいのかという話になる。

なのでこういうのは結局複数登録に対応していないと話にならないのだ。

モッピー!お金がたまるポイントサイト

というわけでHTML側は、こんな感じで。

<div id="app">
  <div>
    <h2>Select an image</h2>
    <input type="file" @change="onFileChange">
  </div>
  <div v-if="images">
      <ol>
          <li v-for="(image, index) in images">
            <h2>{{image.name}}</h2>
            <img :src="image.thumnail" />
            <button @click="images.splice(index, 1)">Remove image</button>
          </li>
      </ol>
    <button @click="submitImage">Submit image</button>
  </div>
</div>

v-for でループさせるわけだが、その中のHTMLマークアップは適当に書いてます。
<li>が基本単位でそれで繰り返し表示にしようということですね。
で、ループを (image, index) in images というように書くと、このループのindex(今何番目か)が取得できる。
それを使って、Removeクリックで、splice(index, 1) とすることで、配列の最初からindex番目の要素を1個削除しようということですね。

js側は、

var app = new Vue({
    el: '#app',
    data: {
        images: []
    },
    methods: {
        onFileChange: function(e){
            var files = e.target.files || e.dataTransfer.files;
            this.createImage(files[0]);
        },
        createImage(file) {
            var image = new Image();
            var reader = new FileReader();
            var vm = this;
            var obj = {};
            reader.onload = function(e) {
                obj.thumnail = e.target.result;
                obj.uploadFile = file;
                obj.name = file.name;
                vm.images.push(obj);
            };
            reader.readAsDataURL(file);
        },
        submitImage: function(e) {
            var formData = new FormData();
            formData.append("number", "123456");
            for (var i = 0; i < this.images.length; i++) {
                formData.append('yourimg' + i, this.images[i].uploadFile);
            }
            var config = {
                headers: {
                    'content-type': 'multipart/form-data'
                }
            };
            axios
                .post('post.php', formData, config)
                .then(function(response) {
                    // response 処理
                    console.log(response);
                })
                .catch(function(error) {
                    // error 処理
                })
        }
    }
});

data は全体は images という配列になっていて、その一個一個が name(ファイル名), thumbnail(画像プレビュー用データ), uploadFile(画像そのもの)というオブジェクトから成っている。
createImage ではファイル情報からオブジェクトを生成して、それをimages配列に追加している。
配列に追加すると、画面に表示される。
remove ボタンクリックでその配列から要素を削除すると、画面も消える。
サーバー側にサブミットする時はformDataに一つずつappendしてpostする。

なんとも、@click="images.splice(index, 1)"これだけで消せてしまうってのがすごいよー。 jquery的にボタンのparentのliの、。。なんて考えなくてよいという。。。

Let It Be

Let It Be