基于vue2.x实现文件上传(w-upload)组件

在线演示地址w-upload

在这一系列的博客里,有一些其他的组件实现过程,有兴趣的童鞋可以了解一下,今天我们来介绍一下w-upload文件上传组件的实现原理。

基于vue2.x实现文件上传(w-upload)组件_第1张图片

实现思路


  • 刚开始写这个的时候我自己也感觉很懵逼,感觉这个原生上传文件的样式咋改,很烦,最后在github上大佬们的实现过程,顿时就感觉这个东西真的很假,就只是让样式变得好看而已,不多说了。来说一下这个的实现过程。

  • 其实原生的上传文件的表单是这样的,我们怎样修改其样式呢,其实是不好改的,既然修改不了,我们就用一个比较特别的方法,这时候就可以凸显出css的强大了,我们通过让input上传文件通过opacity设置为0,然后给其设置为绝对定位,使其脱离文档流,覆盖在我们预期的样式上,这样我们每次点击的是input框,而不是我们预期的button按钮,这样就可以正常触发事件了。


实现过程

  • 子组件以及样式
<div class="upload-block">
    <div class="uploadBtn">
      <w-button v-if="disable" type="primary" class="disable-btn">
        <span>Filespan>
        <i class="w-icon-ascend">i>
      w-button>
      <w-button v-else type="info" class="btn">
        <span>Filespan>
        <i class="w-icon-ascend">i>
      w-button>
      <input v-show="!this.disable" type="file" :multiple="multiple" accept="image/*" ref="file" class="upload-input" />
    div>
    <div class="uploadInfo" :class="showDisableStyle">
      <p class="fileList">
        <span class="placeholder-info" v-show="this.fileNameList.length==0 &&!this.disable&&!this.multiple">请选择一个文件span>
        <span class="placeholder-info" v-show="this.fileNameList.length==0 &&!this.disable&&this.multiple">请选择一个或多个文件span>
        <span class="placeholder-info-disable" v-show="this.disable">不能上传文件span>
        <span class="file-name-block" v-for="(item,index) in fileNameList">{{item.name}}
          <i class="w-icon-close2" @click="removeFile(index)">i>
        span>
      p>
    div>
  div>
  • 我们通过disable来设置我们需要显示的不同按钮,下面中的span标签是根据父组件传回的数值来动态显示提示信息,对于是否设置disable属性,整个组件也有不同的样式,我们设置disable时,原生的input将不会显示,并且设置按钮和提示框的样式,这样达到禁止上传文件的效果。具体样式请看具体链接。
    upload.css

  • 我们通过设置multiple来设置上传的文件时单个文件还是多个文件。

  • 子组件逻辑部分

<script>
 export default {
    name: 'w-upload',
    data(){
      return {
        msg:'File1',
        fileNameList:[],
        active:false
      }
    },
    computed:{
      //显示不同的文件列表底部样式
      showDisableStyle:function () {
         return{
           'upload-disable':this.disable,
           'uploadInfo':!this.disable
         }
      }
    },
    props:{
      disable:Boolean,
      multiple:Boolean,
      value:[Object,FileList,'']
    },
    mounted(){
      const vm = this;
        this.$refs.file.onchange = function(){
          vm.$emit('change',this.files);
          if(this.files.length){
            if(vm.multiple){
              for(let i=0;i<this.files.length;i++){
                vm.fileNameList.push(this.files[i]);
              }
            }else{
              vm.fileNameList = [];//先将数组置空
              vm.fileNameList.push(this.files[0]);
            }
          }
      }
    },
    methods:{
      removeFile:function(id){
        this.fileNameList.splice(id ,1);
        this.$emit('change',this.fileNameList);
      }
    }
  }
script>
  • 我们通过this.$refs.file.onchange来监测input的change事件,通过this.files来获取其上传文件的具体信息,并且保存在fileNameList数组中通过显示列表显示文件名,并且添加删除功能,我们处理过之后通过$emit(change,arg)来向父组件传值,父组件通过回掉函数接收我们传递给父组件的数据。

  • 父组件的写法
export default{
  data(){
    return {
      file:{},
      files:{}
    }
  },
  methods: {
    uploadOneCallback:function(value){
      console.log("我是单个文件父元素接收到的值");
      console.log(value);
      if(value){
        this.fileNameList = value;
      }else{
        this.fileNameList = [];
      }
    },
    uploadManyCallback:function(value){
      console.log("我是多个文件父元素接收到的值");
      console.log(value);
      if(value.length != 0){
        this.fileNameList = value;
      }else{
        console.log("未选择文件");
        this.fileNameList = [];
      }
    }
  }
}

//html部分
<w-upload v-model="file" @change="uploadOneCallback">w-upload>

由于我的开发文档已经写的很详细了,大家详情可以参考我的开发文档来看组件的使用开发文档

Attributes

参数 说明 类型 可选值 默认值
multiple 设定是否多选 Boolean true/false false
disable 是否禁止上传 Boolean true/false false

如果你在使用 WVUE-UI 时遇到问题,或者有好的建议,欢迎给我们提 Email 或 Github

你可能感兴趣的:(vue)