vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)


Posted in Javascript onOctober 15, 2019

说在前面

网上有很多种文件上传的方法,根据公司最近的业务需求,要求实现多种文件的上传,在实现过程中,查阅了很多资料,最后,终于把功能实现了,开心!

<template>
  <div>
    <v-header :left-text="`上传${columnName}`"></v-header>

    <div class="upload">
      <div v-if="columnName === '视频'">
        <div class="forPreview_video" v-for="(item, index) in uploadVideoList" :key="index">
          <video :src="videoSrc"></video>
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadVideoList.length < 2" preview-size="80px" accept="video/*" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div v-if="columnName === '文档'">
        <div class="forPreview_doc" v-for="(item, index) in uploadDocList" :key="index">
          <img src="../../assets/img/resource_doc_b@2x.png" alt="">
          <span>{{item.name}}</span>
          <span>{{item.size | formatSize}}</span>
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadDocList.length < 2" preview-size="80px" accept=".doc, .docx, .xml, .xlsx, .pdf" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div v-if="columnName === '音频'">
        <div class="forPreview_audio" v-for="(item, index) in uploadAudioList" :key="index">
          <img src="../../assets/img/resource_audio@2x.png" alt="">
          <span>{{item.name}}</span>
          <span>{{item.size | formatSize}}</span>
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadAudioList.length < 2" preview-size="80px" accept="audio/*" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div v-if="columnName === '图片'">
        <div class="forPreview_pic" v-for="(item, index) in uploadPicList" :key="index">
          <img :src="picSrc" alt="">
          <van-icon name="delete" @click="delBtn(index)" class="delte"/>
        </div>
        <van-uploader v-show="uploadPicList.length < 2" accept="image/*" preview-size="80px" :before-read="beforeRead" :after-read="afterRead"></van-uploader>
      </div>

      <div class="diy-submit">
        <van-button @click="doSubmit($event)">提交</van-button>
      </div>
    </div>
  </div>
</template>

上述html代码是在同一页面根据前一页面传回的columnName的值来判断需要上传哪种类型文件。

<script>
  import VHeader from '../../common/header'
  import {classifyList, uploadFile, addResources} from '../../http/mock'
  import Toast from 'vant'
  export default {
    name: "uploadFile",
    components: {
      VHeader
    },
    data(){
      return{
        tagList: [], 
        uploadTitle: '',
        currentTag: null,
        tagId: null,
        columnName: localStorage.getItem('columnName'),
        fileIdArr: [],

        uploadVideoList: [], // 选中的上传视频列表
        videoSrc: '',  // 选中的视频的src,用来显示视频
        uploadDocList: [], // 选中的上传文档列表
        uploadAudioList: [], // 选中的上传音频列表
        uploadPicList: [], // 选中的上传图片列表
        picSrc: '', // 选中的图片的src,用来显示图片缩略图
      }
    },
    filters: {
      formatSize(val) { // 格式化文件大小
        if (val > 0) {
          return (val / 1024 / 1024).toFixed(2) + 'M';
        } else {
          return '0M';
        }
      },
    },
    methods: {
      // vant上传文件前校验文件事件
      // 文件选中后先提交给后台,后台根据选中的文件,返回数组(这一业务根据后台而定)
      beforeRead(file){
        let formData = new FormData(); // 为上传文件定义一个formData对象
        let config = {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        };
        let uploadUrl = URL.createObjectURL(file); // 将选中的上传文件转化为二进制文件,显示在页面上
        if(this.columnName === '视频'){
          this.uploadVideoList.push(file);
          this.videoSrc = uploadUrl;
          // 这里使用foreach是为了将选中的多个文件都添加进定义的formdata变量中
          this.uploadVideoList.forEach(item => {
            formData.append(item.name, item)
          })
        }else if(this.columnName === '文档'){
          this.uploadDocList.push(file);
          this.uploadDocList.forEach(item => {
            formData.append(item.name, item)
          })
        }else if(this.columnName === '音频'){
          this.uploadAudioList.push(file);
          this.uploadAudioList.forEach(item => {
            formData.append(item.name, item)
          })
        }else if(this.columnName === '图片'){
          this.uploadPicList.push(file);
          this.picSrc = uploadUrl;
          this.uploadPicList.forEach(item => {
            formData.append(item.name, item)
          })
        }


        // formData.append(file.name, file); // 单个文件上传时可以这么写,上面的foreach就可以删掉
        this.$api.post(uploadFile, formData, config).then(res => {
          this.fileIdArr = res.data.data;  // 把?中的文件?魉徒o後台
        }).catch(err => {
          Toast('文件上?魇?。?)
        })
      },
      // 删除待上传的文件
      delBtn(index){
        if(this.columnName === '视频'){
          // 先判断当前的选中的索引是否是在有效范围中,如果不是则跳出方法 
          if(isNaN(index) || index >= this.uploadVideoList.length){
            return false;
          }
          let tmp = [];
          // 将没被选中的上传文件存放进一个临时数组中
          for(let i = 0; i < this.uploadVideoList.length; i++){
            if(this.uploadVideoList[i] !== this.uploadVideoList[index]){
              tmp.push(this.uploadVideoList[i]);
            }
          }
          // 存放当前未被选中的上传文件
          this.uploadVideoList = tmp;
        }

        if(this.columnName === '文档'){
          console.log(this.uploadDocList.length)
          if(isNaN(index) || index >= this.uploadDocList.length){
            return false;
          }
          let tmp = [];
          for(let i = 0; i < this.uploadDocList.length; i++){
            if(this.uploadDocList[i] !== this.uploadDocList[index]){
              tmp.push(this.uploadDocList[i]);
            }
          }
          this.uploadDocList = tmp;
        }

        if(this.columnName === '音频'){
          if(isNaN(index) || index >= this.uploadAudioList.length){
            return false;
          }
          let tmp = [];
          for(let i = 0; i < this.uploadAudioList.length; i++){
            if(this.uploadAudioList[i] !== this.uploadAudioList[index]){
              tmp.push(this.uploadAudioList[i]);
            }
          }
          this.uploadAudioList = tmp;
        }

        if(this.columnName === '图片'){
          if(isNaN(index) || index >= this.uploadPicList.length){
            return false;
          }
          console.log('uuu')
          let tmp = [];
          for(let i = 0; i < this.uploadPicList.length; i++){
            if(this.uploadPicList[i] !== this.uploadPicList[index]){
              tmp.push(this.uploadPicList[i]);
            }
          }
          this.uploadPicList = tmp;
        }
      },
      doSubmit(){
        let params = {
          classify: this.tagId,    // 针对视频资源时对应的分类id
          file: this.fileIdArr,  // 选择完文件后,调用uploadFile这个接口,后端返回的数组
          resourceColumnId: JSON.parse(localStorage.getItem('columnId')),  // 资源栏目id(视频、图片、音频、文档)
          title: this.uploadTitle  // 上传时填写的标题
        };
        let columnName = localStorage.getItem('columnName')
        this.$api.post(addResources, params).then(res => {
          if(res.data.code === 1001){
            if(columnName === '视频'){
              this.$router.push({name: 'myVideo'});
            }else {
              this.$router.push({name: 'myResourceClassify'});
            }
          }
        }).catch(err => {
          console.log(err)
        })
      },
    },
    mounted(){
      this.getClassifyList();
    }
  }
</script>
<style lang="less" scoped>
  .upload{
    padding: 140px 36px 160px 36px;
    box-sizing: border-box;
  }

  .forPreview_video{
    position: relative;
    /*background: rgba(0,0,0,.7);*/
    video{
      width: 95%;
      max-height: 430px;
    }
    .delte{
      position: absolute;
      right: 0;
      bottom: 0;
    }
  }
  .forPreview_doc, .forPreview_audio{
    display: flex;
    margin-bottom: 10px;
    align-items: center;
    img{
      width: 56px;
      height: 56px;
      margin-right: 20px;
    }
    span:nth-of-type(1){
      flex: 1;
    }
    span:nth-of-type(2){
      margin-right: 20px;
    }
  }
  .forPreview_pic{
    display: flex;
    align-items: flex-end;
    img{
      width: 160px;
      height: 160px;
    }
  }

  .diy-detail{
    width: 100%;
    overflow: hidden;
    
    .btn{
      span{
        margin-bottom: 10px;
      }
    }
    .van-cell{
      background-color: #F0F0F0;
      border-radius: 35px;
      font-size: 26px;
      height: 69px;
      line-height: 69px;
      padding: 0 22px;
      color: #999;
    }
    .van-hairline--top-bottom::after, .van-hairline-unset--top-bottom::after {
      border-width: 0;
    }
    p{
      height: 64px;
      line-height: 64px;
      font-size: 32px;
      color: #333;
      position: relative;
      padding-left: 16px;
    }
    p::before{
      position: absolute;
      top: 0;
      left: 0;
      content: '*';
      color: #FF0000;
    }

    span{
      display: inline-block;
      width: 157px;
      background: #F0F0F0;
      border-radius: 35px;
      color: #999;
      font-size: 26px;
      padding: 14px 18px;
      margin-right: 28px;
      text-align: center;
    }
    .active{
      color: #fff;
      background: linear-gradient(to right,#FD5130,#FA6C34);
    }
  }
  .diy-submit {
    position: fixed;
    height: 150px;
    width: 90%;
    bottom: 0;
    background: #fff;

    .van-button {
      width: 100%;
      height: 90px;
      border-radius: 45px;
      font-size: 36px;
      color: #fff;
      background: linear-gradient(to right, #FD5130, #FA6C34);
      top: 50%;
      transform: translate(0, -50%);
    }
    .van-button--default {
      border: none;
    }
  }
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js 分页全选或反选标识实现代码
Aug 09 Javascript
js控制表单不能输入空格的小例子
Nov 20 Javascript
angularjs 处理多个异步请求方法汇总
Jan 06 Javascript
js判断鼠标左、中、右键哪个被点击的方法
Jan 27 Javascript
js对字符的验证方法汇总
Feb 04 Javascript
JavaScript 消息框效果【实现代码】
Apr 27 Javascript
jquery中each循环的简单回滚操作
May 05 jQuery
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
Aug 23 jQuery
微信小程序之自定义组件的实现代码(附源码)
Aug 02 Javascript
Vue 与 Vuex 的第一次接触遇到的坑
Aug 16 Javascript
Vue组件内部实现一个双向数据绑定的实例代码
Apr 04 Javascript
VUE 项目在IE11白屏报错 SCRIPT1002: 语法错误的解决
Sep 27 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
Oct 15 #Javascript
vue使用@scroll监听滚动事件时,@scroll无效问题的解决方法详解
Oct 15 #Javascript
vue实现树形结构样式和功能的实例代码
Oct 15 #Javascript
谈谈IntersectionObserver懒加载的具体使用
Oct 15 #Javascript
js实现开关灯效果
Mar 30 #Javascript
JS实现灯泡开关特效
Mar 30 #Javascript
浅谈微信小程序列表埋点曝光指南
Oct 15 #Javascript
You might like
php 记录进行累加并显示总时长为秒的结果
2011/11/04 PHP
PHP投票系统防刷票判断流程分析
2012/02/04 PHP
web站点获取用户IP的安全方法 HTTP_X_FORWARDED_FOR检验
2013/06/01 PHP
PHP在不同页面间传递Json数据示例代码
2013/06/08 PHP
php使用Jpgraph绘制简单X-Y坐标图的方法
2015/06/10 PHP
php常用字符串查找函数strstr()与strpos()实例分析
2019/06/21 PHP
javascript 隔行换色函数代码
2010/10/24 Javascript
2010年最佳jQuery插件整理
2010/12/06 Javascript
借助script进行Http跨域请求:JSONP实现原理及代码
2013/03/19 Javascript
js+html5实现canvas绘制圆形图案的方法
2015/06/05 Javascript
javascript 继承学习心得总结
2016/03/17 Javascript
JS 数字转换为大写金额的简单实例
2016/08/04 Javascript
AngularJS动态生成div的ID源码解析
2016/08/29 Javascript
js自制图片放大镜功能
2017/01/24 Javascript
详解angular中通过$location获取路径(参数)的写法
2017/03/21 Javascript
Vue computed计算属性的使用方法
2017/07/14 Javascript
微信小程序 按钮滑动的实现方法
2017/09/27 Javascript
vue mint-ui 实现省市区街道4级联动示例(仿淘宝京东收货地址4级联动)
2017/10/16 Javascript
在Vue项目中使用d3.js的实例代码
2018/05/01 Javascript
利用angular自动编译andriod APK的绕坑经历分享
2019/03/08 Javascript
layui table数据修改的回显方法
2019/09/04 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
2019/11/26 Javascript
koa2 数据api中间件设计模型的实现方法
2020/07/13 Javascript
python实现决策树C4.5算法详解(在ID3基础上改进)
2017/05/31 Python
python+VTK环境搭建及第一个简单程序代码
2017/12/13 Python
对Python中list的倒序索引和切片实例讲解
2018/11/15 Python
Python3.5迭代器与生成器用法实例分析
2019/04/30 Python
Python语言编写智力问答小游戏功能
2020/10/13 Python
如何在windows下安装配置python工具Ulipad
2020/10/27 Python
捷克母婴用品购物网站:Feedo.cz
2020/12/28 全球购物
Jdbc数据访问技术面试题
2012/03/30 面试题
详解如何解决使用JSON.stringify时遇到的循环引用问题
2021/03/23 Javascript
采购求职信
2014/03/17 职场文书
责任书范本
2014/08/25 职场文书
Matplotlib绘制混淆矩阵的实现
2021/05/27 Python
英镑符号 £
2022/02/17 杂记