美文网首页Vue
用vue开发一个图片上传功能

用vue开发一个图片上传功能

作者: 累累的 | 来源:发表于2020-01-09 17:56 被阅读0次

工作中遇到的需求 和大家分享下

  • 以下代码完成图片上传
  • 实线点击预览和删除图片

效果图

图片上传 图片预览删除

该组件上传图片的大致思路

1.利用H5的FileReader对象将上传的图片转成base64格式
2.利用canvas的drawImage方法重绘上传的图片
3.在利用canvas的toDataURL方法将图片压缩
4.将base64文件传递给后台(此项根据自己的项目需求来抉择,我的项目需求就是base64,所以我没有转成blob对象)

文件上传代码

1.使用input标签来获取图片文件

<form ref="uploadForm" id="uploadForm" style="display:inline;">
      <input
        type="file"
        id="fileId"
        ref="addPicFile"
        name="file"
        accept="image/jpg,image/jpeg,image/png,image/bmp"
        style="display:none;"
        @change="addPic"
      />
</form>

2.因为原生的按钮不满足我们需求,所以我们需要手动来做一个添加按钮

 <!-- 项目需求最多不能超过5个图片,所以如果图片有5个我会自动隐藏按钮  -->
<img
      class="addimg-items addBtn"
      v-show="photoList.length < 5"
      src="@/assets/img/添加图片.png"
      @click="$refs.addPicFile.click()"
/>

3.上传图片js

//添加图片
    addPic() {
      // common的upload和compress方法是我自己写得js 我会在下面贴出代码
      let file = common.upload(this.$refs.addPicFile);
      let reader = new FileReader();
      reader.onload = e => {
        let img = new Image();
        img.src = e.target.result;
        img.onload = () => {
          let imgsrc = common.compress(img);
          this.$options.methods.uploadPic.bind(this)(imgsrc);
          // 添加完成之后降input的值清空,如果不清空则会出现无法上传同一个图片的bug
          this.$refs.addPicFile.value = "";
        };
      };
      reader.readAsDataURL(file);
    },
    uploadPic(data) {
      // HTTP是我自己封装的axios的调用代码
      let res = Http.getAxios("POST", `/image/upload`, data);
      res.then(data => {
        // 因为我需要鼠标悬浮图片显示预览和删除按钮, 所以需要imgHover参数
        this.list.push({
          src: data.message,
          imgHover: false
        });
        this.$emit("addPic", this.list);
      });
    }

4.common.js

  //图片压缩
  compress(img) {
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    var width = img.width;
    var height = img.height;
    canvas.width = width;
    canvas.height = height;
    ctx.drawImage(img, 0, 0, width, height);
    var type = "image/jpeg";
    var img64 = canvas.toDataURL(type, 0.3);
    return img64;
  }

  //图片上传
  upload(img) {
    //判断是否支持FileReader
    if (!window.FileReader) {
      this.$Modal.warning({
        title: "警告",
        content: "您的设备不支持图片预览功能,如需该功能请升级您的设备!"
      });
      return;
    }
    var file = img.files[0];
    //是否是图片
    var imageType = /^image\//;
    if (!imageType.test(file.type)) {
      this.$Modal.warning({
        title: "警告",
        content: "请选择图片!"
      });
      return;
    }
    return file;
  }

5.鼠标悬浮显示预览和删除按钮

<div class="showImg" v-for="(item, index) in photoList" :key="item.src">
      <img
        class="addimg-items"
        v-show="photoList.length > 0"
        :src="item.src"
        @mouseenter="enter(item)"
        @mouseleave="leave(item)"
      />
      <div
        class="demo-upload-list-cover"
        v-show="item.imgHover"
        @mouseenter="enter(item)"
        @mouseleave="leave(item)"
      >
        <Icon type="ios-eye" @click="showImg(item.src)" />
        <Icon type="ios-trash" @click="reset(index)" />
      </div>
</div>

6.预览和删除JS操作

    //移入
    enter(item) {
      item.imgHover = true;
    },
    //移出
    leave(item) {
      item.imgHover = false;
    },
    //查看大图
    showImg(src) {
      this.visible = true;
      this.show.photo = src;
    },
    reset(index) {
      this.list.splice(index, 1);
      this.$emit("resetPic", this.list);
    }

7.图片预览,我使用了iView的对话框Modal来预览图片

<Modal title="图片详情" v-model="visible">
      <img :src="show.photo" v-if="visible" style="width: 100%" />
      <div slot="footer"></div>
</Modal>

最后附上全部代码

<style lang="less" scoped>
.showImg {
  position: relative;
  float: left;
  margin-right: 10px;
  .demo-upload-list-cover {
    width: 100px;
    height: 100px;
    padding: 33px 20px;
    i {
      font-size: 30px;
    }
  }
}
.addBtn {
  float: left;
  margin-right: 10px;
}
</style>

<template>
  <div>
    <form ref="uploadForm" id="uploadForm" style="display:inline;">
      <input
        type="file"
        id="fileId"
        ref="addPicFile"
        name="file"
        accept="image/jpg,image/jpeg,image/png,image/bmp"
        style="display:none;"
        @change="addPic"
      />
    </form>
    <div class="showImg" v-for="(item, index) in photoList" :key="item.src">
      <img
        class="addimg-items"
        v-show="photoList.length > 0"
        :src="item.src"
        @mouseenter="enter(item)"
        @mouseleave="leave(item)"
      />
      <div
        class="demo-upload-list-cover"
        v-show="item.imgHover"
        @mouseenter="enter(item)"
        @mouseleave="leave(item)"
      >
        <Icon type="ios-eye" @click="showImg(item.src)" />
        <Icon type="ios-trash" @click="reset(index)" />
      </div>
    </div>
    <img
      class="addimg-items addBtn"
      v-show="photoList.length < 5"
      src="@/assets/img/添加图片.png"
      @click="$refs.addPicFile.click()"
    />
    <Modal title="图片详情" v-model="visible">
      <img :src="show.photo" v-if="visible" style="width: 100%" />
      <div slot="footer"></div>
    </Modal>
  </div>
</template>

<script>
import common from "@/assets/js/common";
import Http from "@/utils/Network/Http";
export default {
  components: {},
  props: ["photo"],
  data() {
    return {
      visible: false,
      show: {
        photo: ""
      },
      photoList: [],
      list: []
    };
  },
  computed: {},
  watch: {},
  methods: {
    //移入
    enter(item) {
      item.imgHover = true;
    },
    //移出
    leave(item) {
      item.imgHover = false;
    },
    //查看大图
    showImg(src) {
      this.visible = true;
      this.show.photo = src;
    },
    //添加图片
    addPic() {
      let file = common.upload(this.$refs.addPicFile);
      let reader = new FileReader();
      reader.onload = e => {
        let img = new Image();
        img.src = e.target.result;
        img.onload = () => {
          let imgsrc = common.compress(img);
          this.$options.methods.uploadPic.bind(this)(imgsrc);
          this.$refs.addPicFile.value = "";
        };
      };
      reader.readAsDataURL(file);
    },
    uploadPic(data) {
      let res = Http.getAxios("POST", `/image/upload`, data);
      res.then(data => {
        this.list.push({
          src: data.message,
          imgHover: false
        });
        this.$emit("addPic", this.list);
      });
    },
    reset(index) {
      this.list.splice(index, 1);
      this.$emit("resetPic", this.list);
    },
    // 清空图片
    clearPic() {
      this.photoList = [];
      this.$emit("clearPic", this.photoList);
    }
  },
  mounted() {
    // 因为修改调用查询方法返回过来的数据会慢一点,所以我延迟赋值了,否则图片将不会展示
    setTimeout(() => {
      this.photoList = this.photo;
      this.list = this.photo;
    }, 300);
  }
};
</script>

相关文章

网友评论

    本文标题:用vue开发一个图片上传功能

    本文链接:https://www.haomeiwen.com/subject/swgyactx.html