引言

一、基础知识

在开始具体实现之前,我们需要了解一些基础知识:

  1. File API:浏览器提供的API,用于处理文件上传。
  2. FileReader:用于读取文件内容的API。
  3. DataURL:一种表示文件内容的方式,通常用于图片预览。
  4. FormData:用于构建一组键值对,表示表单数据,常用于文件上传。

二、实现步骤

1. 创建Vue组件

<template>
  <div>
    <input type="file" multiple @change="handleFileChange" />
    <div class="preview-container">
      <img v-for="(img, index) in previewImages" :key="index" :src="img" alt="preview" />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      previewImages: []
    };
  },
  methods: {
    handleFileChange(event) {
      const files = event.target.files;
      if (files.length === 0) return;

      this.previewImages = []; // 清空之前的预览图片
      Array.from(files).forEach(file => {
        const reader = new FileReader();
        reader.onload = e => {
          this.previewImages.push(e.target.result);
        };
        reader.readAsDataURL(file);
      });
    }
  }
};
</script>

<style>
.preview-container {
  display: flex;
  flex-wrap: wrap;
  margin-top: 20px;
}
.preview-container img {
  width: 100px;
  height: 100px;
  margin-right: 10px;
  margin-bottom: 10px;
}
</style>

2. 解析代码

模板部分

  • <input type="file" multiple @change="handleFileChange" />:一个文件输入框,支持多选文件。当文件选择变化时,触发handleFileChange方法。
  • <div class="preview-container">:用于显示预览图片的容器。
  • <img v-for="(img, index) in previewImages" :key="index" :src="img" alt="preview" />:使用v-for循环显示所有预览图片。

脚本部分

  • data:包含一个previewImages数组,用于存储预览图片的DataURL。
  • handleFileChange方法:处理文件选择事件,读取每个文件并转换为DataURL,然后添加到previewImages数组中。

样式部分

  • 简单的CSS样式,用于展示预览图片。

三、优化与扩展

1. 图片大小和类型

handleFileChange(event) {
  const files = event.target.files;
  if (files.length === 0) return;

  this.previewImages = []; // 清空之前的预览图片
  Array.from(files).forEach(file => {
    if (!file.type.startsWith('image/')) {
      alert('请选择图片文件!');
      return;
    }
    if (file.size > 1024 * 1024 * 5) {
      alert('图片大小不能超过5MB!');
      return;
    }

    const reader = new FileReader();
    reader.onload = e => {
      this.previewImages.push(e.target.result);
    };
    reader.readAsDataURL(file);
  });
}

2. 后端请求

methods: {
  handleFileChange(event) {
    const files = event.target.files;
    if (files.length === 0) return;

    this.previewImages = []; // 清空之前的预览图片
    const formData = new FormData();
    Array.from(files).forEach(file => {
      formData.append('images', file);
      const reader = new FileReader();
      reader.onload = e => {
        this.previewImages.push(e.target.result);
      };
      reader.readAsDataURL(file);
    });

    // 发送请求到后端
    axios.post('/api/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    }).then(response => {
      console.log('上传成功', response);
    }).catch(error => {
      console.error('上传失败', error);
    });
  }
}

四、总结