每日技术:Vue实现上传图片功能

前言:

用vue实现上传图片功能,效果图如下:

先说文件上传控件样式美化怎么做,我有两种方法。

1.先上代码

html部分:

<div class="pics-wrapper">
  <div class="addimg-bg">
    <input type="file" name="uploadImg" class="ipt-file" @change="fileInput">
  </div>
  <ul class="imgshow">
    <li v-for="(item, index) in showImg">
      <img :src="item.url">
      <i class="icon-del" @click="imgDel(item.id)"></i>
    </li>
  </ul>
</div>

CSS(scss)代码如下:

.addimg-wrapper {
  border: 1px solid #dfdfdf;
  border-top: 0;
  height: 153px;
  padding: 25px;
  .pics-wrapper {
    .addimg-bg {
      float: left;
      background: url(../static_img/btn-addpic.png) no-repeat center center;
      width: 78px;
      height: 78px;
    }
    .ipt-file {
      width: 78px;
      height: 78px;
      padding: 0;
      border: 0;
      opacity: 0;
    }
    .imgshow {
      float: left;
      height: 76px;
      font-size: 0;
      li {
        display: inline-block;
        width: 76px;
        height: 76px;
        background-color: #eee;
        border: 1px solid #dfdfdf;
        margin-left: 5px;
        position: relative;
        img {
          width: 100%;
          height: 100%;
        }
        .icon-del {
          display: inline-block;
          position: absolute;
          right: 0;
          top: 0;
          width: 16px;
          height: 16px;
          background: url(../static_img/icon-del.png) no-repeat center center;
        }
      }
    }
  }
}

给input标签外面包一层背景,加号框作为背景,input设置透明度为0

图片素材如下:

btn-addpic.png

icon-del.png

js代码如下:

<script>

new Vue({
  el: '#page-publish',
  data: {
    msg: 'hello world',
    imgData: {
      accept: 'image/gif, image/jpeg, image/png, image/jpg'
    },
    showImg: []
  },
  methods: {
    // 添加并上传图片
    fileInput(e) {
      let img1 = e.target.files[0]
      let type = img1.type
      let size = img1.size
      if (this.imgData.accept.indexOf(type) === -1) {
        alert('请选择我们支持的图片格式!')
        return false
      }
      if (size > 3145728) {
        alert('请选择3M以内的图片!')
        return false
      }
      let fd = new FormData()
      fd.append('Filedata', img1, img1.name)
      axios.post('<{url action=toputil_ctl_uploads@uploads}>', fd, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(res => {
        const data = res.data.data
        this.showImg.push(data)
      }).catch(err => {
        console.log(err)
      })
    },
  }
})

</script>

关键点:

  1. 上传文件file控件的e对象里面有很多信息,其中要用到 e.target.files 
  2. new FormData() 
  3. 请求头header
  4. 请求成功返回的数据存入data中的showImg, v-for循环渲染即可。

但是我需要限制图片数量。最多5张。我可以把这个判断逻辑直接写在fileInput()方法里,但是只要一点击input,就会打开文件选择框,而后才执行fileInput方法里面的代码。这样非常不优雅。所以请看第二种方法。

2.美化上传文件控件第二种方法

Html部分:

<div class="pics-wrapper">
  <div class="addimg-bg" @click="addImg"></div>
  <ul class="imgshow">
    <li v-for="(item, index) in showImg">
      <img :src="item.url">
      <i class="icon-del" @click="imgDel(item.id)"></i>
    </li>
  </ul>
  <input ref="file" type="file" name="uploadImg" class="ipt-file" @change="fileInput">
</div>

CSS代码不变。

Html代码的变化在于单独使用一个div容器显示加号框,和input控件分离。

现在问题是点击加号框的时候如何触发input的change事情,以前用jquery很容易实现的,

jquery版代码:

$(function(){
  $('input').click(function(){
    // do something
  })
  $('a').click(function(){
    $('input').click() // 触发input click事件
  })
})

但这是vue啊!!!

我查了好久,终于...

解决方法如下:

(1)给input加上ref="file"

<input ref="file" type="file" name="uploadImg" class="ipt-file" @change="fileInput">

(2)js代码,在vue methods中添加如下代码

    // 触发添加图片
      addImg () {
        if (this.showImg.length >= 5) {
          alert('晒图仅限5张~')
          return
        }
        this.$refs.file.click()
      },
this.$refs.file.click()

这句是关键。

这样就实现了点击加号框,先判断数量,再触发input控件点击事件。

到这里,添加图片功能实现了,效果如下:

数量超过5张时:

3.删除图片功能

vue methods 中添加如下方法:

// 删除图片
imgDel(id) {
  axios.post('<{url action=toputil_ctl_uploads@deletePic}>', { id: id }).then(res => {
    console.log(res)
    const data = res.data
    if (data.success) {
      this.showImg = this.showImg.filter((n) => {
        return n.id !== id
      })
    } else {
      alert(data.msg)
    }
  })
}

细节没什么要说的,传入要删除的图片id,接口请求成功后,删除相应的数据,用filter方法过滤掉数据。这功能用vue实现还是相当方便。

 该页面其他功能,我会另写博文。到时再贴链接。

-----玩-----

我写技术博客的目的主要是整理自己做过的功能,主要是写给自己看,当然,我尽量写清楚。

若给你造成误解,我很抱歉。若给你带来帮助, 我很欣慰。

有疑问欢迎交流 扣扣:2136946914

原文地址:https://www.cnblogs.com/cathy1024/p/10276618.html