Как показать изображения перед их загрузкой в ​​Vue.js? - PullRequest
0 голосов
/ 31 декабря 2018

После этого учебного пособия я создал этот компонент, который загружает несколько изображений одновременно и показывает имена файлов для загрузки.

Это прекрасно работает, но мне интересно, как я могу показать фотографии (в идеале с определенной максимальной шириной) вместо имен файлов?

      <div v-if="showUploadPhotoModal">
        <transition name="modal">
          <div class="modal-mask">
            <div class="modal-wrapper">

            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header"><strong>{{username}}</strong>&nbsp;&nbsp;
                        <h6 class="modal-title">Upload Photos <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-image"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
                        </h6>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true" @click="showUploadPhotoModal = false">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">


                        <form @submit.prevent="sendFile" enctype="multipart/form-data">
                              <div class="form-group">
                                  <textarea class="form-control" rows="5" v-model="title" placeholder="Title"></textarea>

                              </div>

                              <div v-if="fileError" class="alert alert-danger">{{message}}</div>


                             <label class="upload-btn"><br>
                             <span>
                               <img class="logo img-responsive" src="../assets/images/upload.png">
                               <br>
                             </span>
                                Upload Files <input multiple type="file" @change="selectFile" ref="files" hidden>
                                 <br>

                             </label>
                            </form>   

                    </div>

                  <div class="field">
                    <div v-for="(file, index) in files"  :key="index" class="row photo-list" >

                      <div class="col-10 col-push-6">
                        <div :class="`text-right ${file.invalidMessage ?'red':'black'}`">{{file.name}} 

                          <span v-if="file.invalidMessage!=''">&nbsp; <small>{{file.invalidMessage}}</small> </span>
                        </div>

                      </div>
                      <div class="col-2">
                        <div class="text-left">
                          <a @click.prevent="files.splice(index, 1);uploadFiles.splice(index, 1)" class="remove-btn"> <strong >&times;</strong></a>
                        </div>
                      </div>
                    </div>

                  </div>

                    <span @click="sendFile" class="btn btn-primary">Send</span>

                </div>
            </div>

            </div>
          </div>
        </transition>
      </div>





 data () {
    return { 
        showUploadPhotoModal: false,
        files: [],
        uploadFiles: [],
        title: "",
        message: "",
        fileError: false,


    }
  },
  methods: {
    selectFile() {
      const files = this.$refs.files.files;
      this.uploadFiles = [...this.uploadFiles, ...files];
  this.files = [
       ...this.files,
       ..._.map(files, file => ({
         name: file.name,
         type: file.type,
         invalidMessage: this.validate(file)

       }))
  ];

},

validate(file) {
  const allowedTypes = ["image/jpeg", "image/png", "image/gif"];
  if(!allowedTypes.includes(file.type)) { 
    return "Not an image"
  }
  return "";
},

sendFile() {
  const formData = new FormData();

  formData.append('title', this.title);
  formData.append('token', this.token);

  _.forEach(this.uploadFiles, file => {
    if(this.validate(file)==="") {
      formData.append('files', file);
    }
  });

  axios.post(this.BASE_URL + "/api/post", formData)
  .then(res => {
    console.log('res data is:', res.data);
    this.files=[];
    this.uploadFiles=[];
    })
  .catch(err => {
    console.log('error is', err.response.data.error)
    this.fileError = true;
    });
}


  },

1 Ответ

0 голосов
/ 02 января 2019

Чтобы справиться с этим, я начал с этого макета:

<div id="app" v-cloak>
  <input type="file" multiple accept="image/*"
     @change="handleSelects" name="images">
  <div v-for="image in images">
    <img :src="image" class="preview">
  </div>
</div>

У меня есть тег ввода, использующий @change для запуска метода всякий раз, когда пользователь выбирает некоторые файлы.Под ним у меня есть v-for для итерации и предоставления миниатюр для изображений.

Вот JavaScript:

const app = new Vue({
  el:'#app',
  data:{
    images:[]
  },
  methods:{
    handleSelects(e) {
      this.images = [];
      let fileList = Array.prototype.slice.call(e.target.files);
      fileList.forEach(f => {

        if(!f.type.match("image.*")) {
          return;
        }

        let reader = new FileReader();
        let that = this;

        reader.onload = function (e) {
          that.images.push(e.target.result);
        }
        reader.readAsDataURL(f); 
      });
    }
  }
})

Так что handleSelects делает несколько вещей.Во-первых, он сбрасывает миниатюры (this.images).Затем он просматривает файлы, выбранные во входных данных, проверяет, являются ли они изображениями, и устанавливает FileReader для каждого из них.Для каждого файла он получает URL-адрес данных, который затем добавляется в этот массив изображений, чтобы можно было создавать предварительные просмотры.

Вы можете увидеть полный CodePen этого здесь: https://codepen.io/cfjedimaster/pen/VqrGQw?editors=1111

...