• 2/17 Vue 上传图片并预览的实现 ( 完 )


    写在前面

      之前我写了一个刚刚好的没有涉及到提交方面的问题的 html 

      大家可以参考一下 ( 直接复制就能用 )

      https://www.cnblogs.com/WaterMealone/p/14407875.html

      今天连着 express 暂时把这个组件搞出来了

      有些关于底层的问题 我暂时解决不了 只能曲线救组件....


    组件如何引用

      

      暂时还没有涉及到 userId 的部分只是先打了一个预防针而已

      然后就是一个“玩具”变量 就是上传的大小限制

      演示的动画

      

    一些变量

      我写的时候,没有仔细思考,只是看着想加一个就弄一个,然后这个组件的逻辑可能不是

      很清晰

      我先把一些变量说一下

      1.父组件的参数

        这个应该不用难理解

        

      2.data

        

     1 props: {
     2     userId: {
     3       type: String,
     4       validator(value) {
     5         //  判断String是否为空
     6         return value === "" ? false : true;
     7       },
     8       default: "",
     9     },
    10 
    11     maxSize: {
    12       type: Number,
    13       validator(value) {
    14         return value > 0 ? true : false;
    15       },
    16       default: 10,
    17     },
    18   },
    19   data() {
    20     return {
    21       // 预展示的图片对象数组
    22       preFiles: [],
    23 
    24       // 渲染列表
    25       preFilesLength: 0,
    26 
    27       // 这个是渲染list的过程 渲染到第几个li
    28       updateState: 0,
    29 
    30       // 真正要上传的图片文件
    31       files: [],
    32 
    33       // 选择上传的文件 之前想到了更改 但是没有成功 就留下一个响应的变量 可以删除的
    34       select: "全选",
    35 
    36       // 是否进行拖动事件
    37       isDrag: false,
    38 
    39       // 上传进度 0 表示还未开始 1 表示开始上传 2 表示结束上传
    40       uploadStatu: 0,
    41     };
    42   },
    View Code

    开始写代码

       首先,我们得确定怎么来弄这个东西

      我最初的想法就是,就是普通的上传,可以拖文件上传,然后显示预览,然后选择自己想要上传的文件

      ...

      然后我先把最初的还没有涉及拖动文件的那一部分,先弄了出来 然后缝缝补补开始弄

      1.第一部分

      

      其实这里这个部分最主要的就是对于 label 标签的运用

        ( 我点击这个 div 相当于点击的是 input  )

      

      这里有一个方法,当 input 标签变化的时候传入事件的 target ( 可以自己看一下 事件 的target )

     storepreFiles(obj) {
            // 如果当前的上传状态是 0-未上传 
          if (this.uploadStatu === 0) {
            // 获取input里面的文件组
            var fileList = obj.files;
            // 先判定有没有重复提交的文件 可以加判断条件
            for (let i = 0; i < fileList.length; i++) {
              for (let j = 0; j < this.preFiles.length; j++) {
                if (this.preFiles[j].name === fileList[i].name) {
                  alert("有文件重复");
                  return;
                }
              }
            }
    
            //  这个是处理 显示 有多少个文件在列表的情况 ( 因为可以在未上传的时候 继续添加 )
            this.preFilesLength = this.preFilesLength + fileList.length;
    
            // 进行整合 ( 如果直接用push的话 这样会变成 两个Filelist 对象 组合 )
            for (var i = 0; i < fileList.length; i++) {
              this.files = this.files.concat(fileList[i]);
            }
    
            // 下面的作用域会变
            var vue = this;
            // 对文件组进行遍历,可以到控制台打印出fileList去看看
            // for里面的执行机制很奇怪 这里经过验证用了 promise 但是 还是发现写入的时候, 执行顺序是乱的
            for (let i = 0; i < fileList.length; i++) {
              function uploadFile(file) {
                return new Promise(function (resolve, reject) {
                  let reader = new FileReader();
                  //  将file(图片) 读取为一个 DataUrl 可以直接用 img 里面的 src 进行展示
                  reader.readAsDataURL(file);
                  reader.onload = function () {
                    resolve(this.result);
                  };
                });
              }
              uploadFile(fileList[i]).then(function (result) {
                console.group(i);
                console.log(event);
                console.log(fileList[i]);
                console.groupEnd();
                // vue.preFiles.splice(i, 0, { name: fileList[i].name, size: fileList[i].size, index: 0, })
                vue.preFiles.push({
                  name: fileList[i].name,
                  size: fileList[i].size,
                  index: 0,
                  src: result,
                  isChecked: true,
                });
              });
            }
          } else {
            alert("已经上传完毕!");
          }
        },

       2.第二部分

      

      首先我们得确定现在是 不是 为上传状态 非0 或者是 files || preFiles 里面 不是空的

      其实上面的那个 storepreFiles 的主要目的 就是存储一个 预览文件图片的对象 数组 就是 preFiles 

      html 中 有些地方 可以对照着看

      比如加载进度条这个地方 其实是对 preFiles 进行了 watch  

      当 preFiles 发生改变 进行 侦听 

      先 “过滤” 并不是这个时候的更新条件( 比如只是数组内一个对象属性的改变 必须得过滤 我们需要的是整个数组中元素的增加或者减少 ),然后才进行操作

      

       

       这里不过于细写 因为牵扯到后面的内容了

            <div class="show-file-box" v-if="preFiles.length == 0 ? false : true">
              <div class="text-container">
                <span>上传列表</span>
                <span>{{ updateState }} / {{ preFilesLength }}</span>
              </div>
              <!-- 渲染出来的情况 有一个进度条 -->
              <div class="pre-upload-bar">
                <div>
                  <span
                    >列表加载进度
                    {{ (updateState / preFilesLength).toFixed(1) * 100 }} %</span
                  >
                </div>
                <div
                  class="pre-upload-bar-done"
                  :style="{  (updateState / preFilesLength) * 100 + '%' }"
                ></div>
              </div>
              <!-- <div v-if="updateState === preFilesLength ? true : false"> -->
    
              <ul class="pre-upload-list">
                <transition-group tag="li" name="list">
                  <li
                    class="pre-upload-file"
                    v-for="file in preFiles"
                    :key="file.name"
                  >
                    <div class="review">
                      <!-- 图片预览 -->
                      <div class="review-image-container">
                        <img class="review-image" :src="file.src" />
                      </div>
    
                      <div class="review-file-name-container">
                        <span class="file-name"> {{ file.name }}</span>
                      </div>
                      <div class="progress">
                        <div
                          class="progress-done"
                          :style="{  file.index + '%' }"
                        ></div>
                      </div>
                      <span class="percent">{{ file.index }}%</span>
                      <input
                        v-if="uploadStatu === 0 ? true : false"
                        class="select-box"
                        check
                        type="checkbox"
                        name="select"
                        :value="file.name"
                        :checked="file.isChecked"
                        @change="doSelect(file.name)"
                        ref="select"
                      />
                    </div>
                  </li>
                </transition-group>
              </ul>

      3.第三部分

      

      

      这个地方 其实是最简单的地方,只需要对我们现存的 preFiles 数组里面的对象的属性进行操作 就行了 ( 全选按钮 )

      

     1    <hr color="lightpink" style="margin: 10px 8px" />
     2           <!-- 选择按钮 -->
     3           <div class="bottom">
     4             <div
     5               class="bottom-shelter"
     6               v-if="updateState != preFilesLength"
     7             ></div>
     8             <div class="bottom-content">
     9               <div class="bottom-select">
    10                 <span
    11                   class="bottom-select-button"
    12                   @click="seletAll"
    13                   v-if="uploadStatu === 0 ? true : false"
    14                 >
    15                   {{ select }}</span
    16                 >
    17                 <div class="bottom-select-info">
    18                   <div>
    19                     <span>已选</span>
    20                     <span
    21                       class="span-special"
    22                       :style="{ color: showSize() > maxSize ? 'red' : 'green' }"
    23                       >{{ showSelect() }}
    24                     </span>
    25                     <span>/{{ preFilesLength }}</span>
    26                   </div>
    27                   <div>
    28                     <span
    29                       class="span-special"
    30                       :style="{ color: showSize() > maxSize ? 'red' : 'green' }"
    31                       >{{ showSize() }}
    32                     </span>
    33                     <span>/ {{ showAllSize() }} mb </span>
    34                   </div>
    35                 </div>
    36               </div>
    37 
    38               <div
    39                 class="upload-statu-info"
    40                 v-if="uploadStatu == 0 ? false : true"
    41               >
    42                 <span>{{ uploadStatu == 1 ? "上传ing" : "" }}</span>
    43                 <span>{{ uploadStatu == 2 ? "上传完成" : "" }}</span>
    44               </div>
    45 
    46               <div
    47                 class="bottom-upload"
    48                 @click="upload"
    49                 v-if="uploadStatu === 0 ? true : false"
    50               >
    51                 <span>上传</span>
    52               </div>
    53 
    54               <div
    55                 class="bottom-upload"
    56                 @click="continueUpload"
    57                 v-if="uploadStatu === 2 ? true : false"
    58               >
    59                 <span>清空列表</span>
    60               </div>
    61             </div>
    62           </div>

      

    全部代码

      简单的组成就是这样,但是细说肯定很难说,推荐有缘人直接拿着我的代码 注册一个组件看

      1 <template>
      2   <div id="app">
      3     <div class="container">
      4       <div class="title-container">
      5         <span>上传文件</span>
      6       </div>
      7 
      8       <div class="upload-box">
      9         <!--  上传的那个框框 -->
     10         <div
     11           class="drag-box"
     12           ref="dragBox"
     13           :class="isDrag ? 'draging-drag-box' : ''"
     14         >
     15           <label>
     16             <div class="icon-container">
     17               <i
     18                 class="fa fa-file"
     19                 :class="isDrag ? 'draging-fa-file' : ''"
     20               ></i>
     21             </div>
     22             <div class="label-text-container">
     23               <span :class="isDrag ? 'draging-label-text-container' : ''"
     24                 >请将文件拖动至此</span
     25               >
     26               <br />
     27               <span :class="isDrag ? 'draging-label-text-container' : ''"
     28                 >或者单击上传</span
     29               >
     30             </div>
     31             <input
     32               type="file"
     33               accept="image/jepg, image/png"
     34               name="pictures"
     35               @change="storepreFiles($event.target)"
     36               multiple
     37             />
     38           </label>
     39         </div>
     40 
     41         <div class="show-file-box" v-if="preFiles.length == 0 ? false : true">
     42           <div class="text-container">
     43             <span>上传列表</span>
     44             <span>{{ updateState }} / {{ preFilesLength }}</span>
     45           </div>
     46           <!-- 渲染出来的情况 有一个进度条 -->
     47           <div class="pre-upload-bar">
     48             <div>
     49               <span
     50                 >列表加载进度
     51                 {{ (updateState / preFilesLength).toFixed(1) * 100 }} %</span
     52               >
     53             </div>
     54             <div
     55               class="pre-upload-bar-done"
     56               :style="{  (updateState / preFilesLength) * 100 + '%' }"
     57             ></div>
     58           </div>
     59           <!-- <div v-if="updateState === preFilesLength ? true : false"> -->
     60 
     61           <ul class="pre-upload-list">
     62             <transition-group tag="li" name="list">
     63               <li
     64                 class="pre-upload-file"
     65                 v-for="file in preFiles"
     66                 :key="file.name"
     67               >
     68                 <div class="review">
     69                   <!-- 图片预览 -->
     70                   <div class="review-image-container">
     71                     <img class="review-image" :src="file.src" />
     72                   </div>
     73 
     74                   <div class="review-file-name-container">
     75                     <span class="file-name"> {{ file.name }}</span>
     76                   </div>
     77                   <div class="progress">
     78                     <div
     79                       class="progress-done"
     80                       :style="{  file.index + '%' }"
     81                     ></div>
     82                   </div>
     83                   <span class="percent">{{ file.index }}%</span>
     84                   <input
     85                     v-if="uploadStatu === 0 ? true : false"
     86                     class="select-box"
     87                     check
     88                     type="checkbox"
     89                     name="select"
     90                     :value="file.name"
     91                     :checked="file.isChecked"
     92                     @change="doSelect(file.name)"
     93                     ref="select"
     94                   />
     95                 </div>
     96               </li>
     97             </transition-group>
     98           </ul>
     99 
    100           <hr color="lightpink" style="margin: 10px 8px" />
    101           <!-- 选择按钮 -->
    102           <div class="bottom">
    103             <div
    104               class="bottom-shelter"
    105               v-if="updateState != preFilesLength"
    106             ></div>
    107             <div class="bottom-content">
    108               <div class="bottom-select">
    109                 <span
    110                   class="bottom-select-button"
    111                   @click="seletAll"
    112                   v-if="uploadStatu === 0 ? true : false"
    113                 >
    114                   {{ select }}</span
    115                 >
    116                 <div class="bottom-select-info">
    117                   <div>
    118                     <span>已选</span>
    119                     <span
    120                       class="span-special"
    121                       :style="{ color: showSize() > maxSize ? 'red' : 'green' }"
    122                       >{{ showSelect() }}
    123                     </span>
    124                     <span>/{{ preFilesLength }}</span>
    125                   </div>
    126                   <div>
    127                     <span
    128                       class="span-special"
    129                       :style="{ color: showSize() > maxSize ? 'red' : 'green' }"
    130                       >{{ showSize() }}
    131                     </span>
    132                     <span>/ {{ showAllSize() }} mb </span>
    133                   </div>
    134                 </div>
    135               </div>
    136 
    137               <div
    138                 class="upload-statu-info"
    139                 v-if="uploadStatu == 0 ? false : true"
    140               >
    141                 <span>{{ uploadStatu == 1 ? "上传ing" : "" }}</span>
    142                 <span>{{ uploadStatu == 2 ? "上传完成" : "" }}</span>
    143               </div>
    144 
    145               <div
    146                 class="bottom-upload"
    147                 @click="upload"
    148                 v-if="uploadStatu === 0 ? true : false"
    149               >
    150                 <span>上传</span>
    151               </div>
    152 
    153               <div
    154                 class="bottom-upload"
    155                 @click="continueUpload"
    156                 v-if="uploadStatu === 2 ? true : false"
    157               >
    158                 <span>清空列表</span>
    159               </div>
    160             </div>
    161           </div>
    162         </div>
    163       </div>
    164     </div>
    165   </div>
    166 </template>
    167 
    168 <script>
    169 export default {
    170   name: "upload",
    171   props: {
    172     userId: {
    173       type: String,
    174       validator(value) {
    175         //  判断String是否为空
    176         return value === "" ? false : true;
    177       },
    178       default: "",
    179     },
    180 
    181     maxSize: {
    182       type: Number,
    183       validator(value) {
    184         return value > 0 ? true : false;
    185       },
    186       default: 10,
    187     },
    188   },
    189   data() {
    190     return {
    191       // 预展示的图片对象数组
    192       preFiles: [],
    193 
    194       // 渲染列表
    195       preFilesLength: 0,
    196 
    197       // 这个是渲染list的过程 渲染到第几个li
    198       updateState: 0,
    199 
    200       // 真正要上传的图片文件
    201       files: [],
    202 
    203       // 选择上传的文件 之前想到了更改 但是没有成功 就留下一个响应的变量 可以删除的
    204       select: "全选",
    205 
    206       // 是否进行拖动事件
    207       isDrag: false,
    208 
    209       // 上传进度 0 表示还未开始 1 表示开始上传 2 表示结束上传
    210       uploadStatu: 0,
    211     };
    212   },
    213   updated() {},
    214   mounted: function () {
    215     var dragBox = this.$refs.dragBox;
    216     dragBox.addEventListener("dragenter", this.onDrag, false);
    217     dragBox.addEventListener("dragover", this.onDrag, false);
    218     dragBox.addEventListener(
    219       "dragleave",
    220       () => {
    221         this.isDrag = false;
    222       },
    223       false
    224     );
    225     dragBox.addEventListener("drop", this.onDrop, false);
    226   },
    227   watch: {
    228     // 通过对 preFiles 监听 实现简单加载文件进度条
    229     preFiles: {
    230       handler: "updateS",
    231     },
    232   },
    233   methods: {
    234     storepreFiles(obj) {
    235         // 如果当前的上传状态是 0-未上传 
    236       if (this.uploadStatu === 0) {
    237         // 获取input里面的文件组
    238         var fileList = obj.files;
    239         // 先判定有没有重复提交的文件 可以加判断条件
    240         for (let i = 0; i < fileList.length; i++) {
    241           for (let j = 0; j < this.preFiles.length; j++) {
    242             if (this.preFiles[j].name === fileList[i].name) {
    243               alert("有文件重复");
    244               return;
    245             }
    246           }
    247         }
    248 
    249         //  这个是处理 显示 有多少个文件在列表的情况 ( 因为可以在未上传的时候 继续添加 )
    250         this.preFilesLength = this.preFilesLength + fileList.length;
    251 
    252         // 进行整合 ( 如果直接用push的话 这样会变成 两个Filelist 对象 组合 )
    253         for (var i = 0; i < fileList.length; i++) {
    254           this.files = this.files.concat(fileList[i]);
    255         }
    256 
    257         // 下面的作用域会变
    258         var vue = this;
    259         // 对文件组进行遍历,可以到控制台打印出fileList去看看
    260         // for里面的执行机制很奇怪 这里经过验证用了 promise 但是 还是发现写入的时候, 执行顺序是乱的
    261         for (let i = 0; i < fileList.length; i++) {
    262           function uploadFile(file) {
    263             return new Promise(function (resolve, reject) {
    264               let reader = new FileReader();
    265               //  将file(图片) 读取为一个 DataUrl 可以直接用 img 里面的 src 进行展示
    266               reader.readAsDataURL(file);
    267               reader.onload = function () {
    268                 resolve(this.result);
    269               };
    270             });
    271           }
    272           uploadFile(fileList[i]).then(function (result) {
    273             console.group(i);
    274             console.log(event);
    275             console.log(fileList[i]);
    276             console.groupEnd();
    277             // vue.preFiles.splice(i, 0, { name: fileList[i].name, size: fileList[i].size, index: 0, })
    278             vue.preFiles.push({
    279               name: fileList[i].name,
    280               size: fileList[i].size,
    281               index: 0,
    282               src: result,
    283               isChecked: true,
    284             });
    285           });
    286         }
    287       } else {
    288         alert("已经上传完毕!");
    289       }
    290     },
    291 
    292     // 渲染列表的参数
    293     updateS() {
    294       if (this.updateState >= this.preFilesLength) {
    295         // this.preFilesLength = this.preFilesLength - this.preFiles.filter(item => item.isChecked == false).length;
    296         this.updateState =
    297           this.updateState - (this.preFilesLength - this.preFiles.length);
    298       } else {
    299         this.updateState = this.updateState + 1;
    300       }
    301     },
    302 
    303     findPreFile(name) {
    304       let that = this;
    305       return this.preFiles.find((item, index) => {
    306         return item.name === name;
    307       });
    308     },
    309 
    310     // 点击 选择框 和 全选
    311     doSelect(name) {
    312       this.preFiles.forEach((element) => {
    313         if (element.name == name) {
    314           element.isChecked = !element.isChecked;
    315         }
    316       });
    317     },
    318     seletAll() {
    319       if (this.$refs.select.find((item) => item.checked == false)) {
    320         console.log(this.$refs.select);
    321         this.preFiles.forEach((element) => {
    322           element.isChecked = true;
    323         });
    324       }
    325     },
    326 
    327     // 显示 选中个数 和 显示 选中的文件大小
    328     showSelect() {
    329       let num = 0;
    330       this.preFiles.forEach((element) => {
    331         if (element.isChecked == true) {
    332           num++;
    333         }
    334       });
    335       return num;
    336     },
    337 
    338     showSize() {
    339       let size = 0;
    340       this.preFiles.forEach((element) => {
    341         if (element.isChecked == true) {
    342           size = size + element.size;
    343         }
    344       });
    345       return (size / Math.pow(2, 20)).toFixed(2);
    346     },
    347 
    348     showAllSize() {
    349       let size = 0;
    350       this.preFiles.forEach((element) => {
    351         size = size + element.size;
    352       });
    353       return (size / Math.pow(2, 20)).toFixed(2);
    354     },
    355 
    356     // 拖动文件上传
    357     onDrag: function (e) {
    358       this.isDrag = true;
    359       // 取消默认事件
    360       e.stopPropagation();
    361       e.preventDefault();
    362     },
    363 
    364     onDragLeave(e) {},
    365 
    366     onDrop: function (e) {
    367       this.isDrag = false;
    368       e.stopPropagation();
    369       e.preventDefault();
    370       var dt = e.dataTransfer;
    371       this.storepreFiles(dt);
    372     },
    373 
    374     // 继续文件上传 慎重使用这个方法
    375     continueUpload() {
    376       this.uploadStatu = 0;
    377       this.preFiles = [];
    378       this.files = [];
    379       this.preFilesLength = this.files.length;
    380       this.updateState = 0;
    381     },
    382     // 文件上传
    383     // 确定上传文件 通过  preFiles 的 isChecked 属性 取得每个文件的 name 和 真正要上传的文件的 name 交叉对比
    384     checkFiles() {
    385       console.log(this.preFiles);
    386       if (
    387         this.preFiles != this.preFiles.filter((item) => item.isChecked == true)
    388       ) {
    389         this.preFiles = this.preFiles.filter((item) => item.isChecked == true);
    390       }
    391       let vue = this;
    392       function thisFirst() {
    393         return new Promise(function (resolve, reject) {
    394           for (let i = 0; i < vue.files.length; i++) {
    395             var that = vue;
    396             function first(i, j) {
    397               return new Promise(function (resolve, reject) {
    398                 let flag = 1;
    399                 for (let j = 0; j < vue.preFiles.length; j++) {
    400                   if (that.files[i].name === that.preFiles[j].name) {
    401                     flag = flag * 0;
    402                   } else {
    403                     flag = flag * 1;
    404                   }
    405                   console.group(i);
    406                   console.log(that.files[i].name);
    407                   console.log(that.preFiles[j].name);
    408                   console.log(flag + " " + i);
    409                   console.log({ flag, i });
    410                   console.groupEnd();
    411                 }
    412                 resolve({ flag: flag, i: i });
    413               });
    414             }
    415 
    416             first(i).then((obj) => {
    417               console.log(obj);
    418               if (obj.flag != 0) {
    419                 delete that.files[obj.i];
    420               }
    421             });
    422             // }
    423           }
    424           resolve();
    425         });
    426       }
    427 
    428       thisFirst().then(() => {
    429         vue.files = vue.files.filter((item) => item != "undefined");
    430         vue.preFilesLength = vue.files.length;
    431         vue.updateState = vue.files.length;
    432       });
    433     },
    434     upload() {
    435       if (this.showSize() == 0) {
    436         alert("您 啥也没选 选个毛");
    437       }
    438       if (this.maxSize < this.showSize()) {
    439         alert("文件太大!请重新选择!");
    440       } else {
    441         let vue = this;
    442         function firstDo() {
    443           return new Promise(function (resolve, reject) {
    444             if (vue.preFilesLength != 0) {
    445               vue.checkFiles();
    446               vue.preFilesLength = vue.files.length;
    447               console.log("updating " + vue.preFiles);
    448             }
    449             resolve();
    450           });
    451         }
    452 
    453         firstDo().then(() => {
    454           vue.files.forEach((element) => {
    455             vue.uploadSingleFile(element);
    456           });
    457           vue.uploadStatu = 2;
    458         });
    459       }
    460     },
    461 
    462     uploadSingleFile(file) {
    463       // 先找到匹配的 预览文件 位置 方便写入 index
    464 
    465       let position = 0;
    466       this.preFiles.forEach((element) => {
    467         if (element.name == file.name) {
    468           position = this.preFiles.indexOf(element);
    469         }
    470       });
    471 
    472       this.uploadStatu = 1;
    473 
    474       let param = new FormData(); // 创建form对象
    475       param.append("file", file); // 通过append向form对象添加数据
    476       console.log(param.get("file")); // FormData私有类对象,访问不到,可以通过get判断值是否传进去
    477       let vue = this;
    478       vue.axios
    479         .post("/demo/upload_test", param, {
    480           // 给个请求头,让后端知道应该怎么处理数据
    481           headers: {
    482             "Content-Type": "multipart/form-data",
    483           },
    484           onUploadProgress: (progressEvent) => {
    485             let processStatu =
    486               ((progressEvent.loaded / progressEvent.total) * 100) | 0;
    487             vue.preFiles[position].index = processStatu;
    488           },
    489         })
    490         .then((response) => {
    491           console.log(response.data);
    492         });
    493     },
    494   },
    495 };
    496 </script>
    497 
    498 <style scoped>
    499 span {
    500   font-weight: 700;
    501   font: bolder;
    502 }
    503 
    504 .container {
    505   width: 450px;
    506   /* background-color: rgb(195, 209, 228); */
    507   box-shadow: 2px 2px 2px 2px rgba(68, 68, 68, 0.2);
    508   border-radius: 10px;
    509   padding: 20px;
    510 }
    511 
    512 .upload-box {
    513   /*  400px; */
    514   /* height: 400px; */
    515 }
    516 
    517 .title-container {
    518   margin: 10px 8px 20px 8px;
    519   font-size: 20px;
    520 
    521   border-radius: 5px;
    522   background: linear-gradient(to right, rgb(112, 158, 242), rgb(255, 255, 255));
    523   color: white;
    524 }
    525 
    526 .drag-box {
    527   padding: 20px;
    528   margin: 10px auto;
    529   width: 380px;
    530   border-radius: 10px;
    531   border: 5px dashed rgba(112, 155, 248, 0.7);
    532   text-align: center;
    533   transition: all linear 0.1s;
    534 }
    535 
    536 .label-text-container {
    537   margin: 20px 8px;
    538   font-size: 20px;
    539 }
    540 
    541 .text-container {
    542   margin: 20px 8px;
    543   font-size: 20px;
    544   border-radius: 5px;
    545   background: linear-gradient(to right, rgb(112, 158, 242), rgb(255, 255, 255));
    546   color: white;
    547 }
    548 
    549 .drag-box .label-text-container {
    550   color: rgba(190, 190, 190, 0.8);
    551   transition: all linear 0.1s;
    552 }
    553 
    554 .icon-container {
    555   margin: 15px;
    556 }
    557 
    558 .fa-file {
    559   color: rgba(247, 187, 219, 0.8);
    560   font-size: 100px;
    561   transition: all linear 0.1s;
    562 }
    563 
    564 /*  当进入文件的时候添加css */
    565 .drag-box:hover {
    566   border: 5px dashed rgba(112, 155, 248, 1);
    567 }
    568 
    569 .drag-box:hover .fa-file {
    570   color: rgb(245, 124, 188);
    571 }
    572 
    573 .drag-box:hover .label-text-container {
    574   color: rgb(68, 68, 68);
    575 }
    576 
    577 /*  当拖动文件的时候添加css */
    578 .draging-drag-box {
    579   border: 5px dashed rgba(112, 155, 248, 1);
    580 }
    581 
    582 .draging-fa-file {
    583   color: rgb(245, 124, 188);
    584 }
    585 
    586 .draging-label-text-container {
    587   color: rgb(68, 68, 68);
    588 }
    589 
    590 /*  点击上传文件的时候的那个input */
    591 label input {
    592   display: none;
    593 }
    594 
    595 .review {
    596   border: 1px solid transparent;
    597   border-radius: 5px;
    598   color: #777;
    599   display: flex;
    600   font-size: 12px;
    601   align-items: center;
    602   padding: 10px;
    603   margin: 5px 8px;
    604 }
    605 
    606 .review:hover {
    607   cursor: pointer;
    608   /* border: 1px solid #ddd; */
    609   box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 0.7);
    610 }
    611 
    612 .pre-upload-bar {
    613   margin: 10px 10px;
    614   height: 20px;
    615 }
    616 
    617 .pre-upload-bar span {
    618   font-size: 12px;
    619   font-weight: 20px;
    620   color: #777;
    621 }
    622 
    623 .pre-upload-bar-done {
    624   background: linear-gradient(to left, rgb(112, 158, 242), rgb(119, 140, 255));
    625   box-shadow: 0 3px 3px -5px rgb(100, 115, 143), rgb(134, 138, 165);
    626   border-radius: 5px;
    627   height: 3px;
    628   width: 0;
    629   transition: width ease 0.2s;
    630 }
    631 
    632 .review-file-name-container {
    633   width: 100px;
    634 }
    635 
    636 .review-image-container {
    637   margin: 0 8px 0 0;
    638 }
    639 
    640 .review-image {
    641   width: 50px;
    642 }
    643 
    644 .pre-upload-list {
    645   list-style: none;
    646   /*  取消缩进 */
    647   margin: 0px;
    648   padding: 0px;
    649 }
    650 
    651 .file-name {
    652   width: 100%;
    653   float: left;
    654   overflow: hidden;
    655   text-overflow: ellipsis;
    656   white-space: normal;
    657 }
    658 
    659 .progress {
    660   background-color: rgba(100, 100, 100, 0.2);
    661   border-radius: 5px;
    662   position: relative;
    663   margin: 0 10px;
    664   height: 10px;
    665   width: 150px;
    666 }
    667 
    668 .progress-done {
    669   background: linear-gradient(to left, rgb(242, 112, 156), rgb(255, 148, 114));
    670   box-shadow: 0 3px 3px -5px rgb(242, 112, 156), 0 2px 5px rgb(242, 112, 156);
    671   border-radius: 5px;
    672   height: 10px;
    673   width: 0;
    674   transition: width ease 0.1s;
    675 }
    676 
    677 .select-box {
    678   width: 20px;
    679   height: 20px;
    680   margin: 0 0 0 36px;
    681 }
    682 
    683 /* list的transition group */
    684 .list-enter,
    685 .list-leave-to {
    686   opacity: 0;
    687 }
    688 
    689 .list-enter-active {
    690   animation: moveIn 1s;
    691 }
    692 
    693 .list-leave-active {
    694   animation: moveOut 1s;
    695   /* transition: all 1s linear; */
    696 }
    697 
    698 @keyframes moveIn {
    699   0% {
    700     opacity: 0;
    701     transform: translate(30px, 15px);
    702   }
    703 
    704   30% {
    705     opacity: 0.5;
    706     transform: translate(0px, 15px);
    707   }
    708 
    709   100% {
    710     opacity: 1;
    711     transform: translate(0, 0px);
    712   }
    713 }
    714 
    715 @keyframes moveOut {
    716   0% {
    717     opacity: 1;
    718     transform: translate(0, 0px);
    719   }
    720 
    721   30% {
    722     opacity: 0.5;
    723     transform: translate(0px, 15px);
    724   }
    725 
    726   100% {
    727     opacity: 0;
    728     transform: translate(30px, 15px);
    729   }
    730 }
    731 .upload-statu-info {
    732   padding: 0 10px;
    733   margin: 3px 8px;
    734 }
    735 .upload-statu-info span {
    736   letter-spacing: 5px;
    737   font-weight: 300px;
    738 }
    739 
    740 .bottom-select {
    741   margin: 5px 8px;
    742   padding: 0 10px;
    743   height: 40px;
    744 }
    745 
    746 .bottom-select .bottom-select-button {
    747   cursor: pointer;
    748   color: white;
    749   margin: 5px;
    750   padding: 7px;
    751   float: right;
    752   transition: all linear 0.1s;
    753   background-color: rgb(247, 159, 172);
    754   border-radius: 5px;
    755 }
    756 
    757 .bottom-select-info span {
    758   font-size: 15px;
    759   font-weight: 200;
    760 }
    761 
    762 .bottom-select-info .span-special {
    763   font-weight: 1000;
    764 }
    765 
    766 .bottom-upload {
    767   margin: 5% auto;
    768   width: 160px;
    769   height: 40px;
    770   text-align: center;
    771   padding: 5px;
    772   border-radius: 5px;
    773   background-color: lightpink;
    774   color: white;
    775   cursor: pointer;
    776 }
    777 
    778 .bottom-upload span {
    779   letter-spacing: 5px;
    780   margin: auto;
    781   font-size: 30px;
    782 }
    783 
    784 .bottom {
    785   position: relative;
    786   width: 450px;
    787   height: 150px;
    788 }
    789 
    790 .bottom-shelter {
    791   position: absolute;
    792   width: 100%;
    793   height: 150px;
    794   cursor: not-allowed;
    795   z-index: 1;
    796 }
    797 
    798 .bottom-content {
    799   width: 100%;
    800   position: absolute;
    801   z-index: 0;
    802 }
    803 </style>
    View Code

    总结

      这个代码其实还是有些地方有问题的,比如 for 循环在用 fileReader 将图片读为 dataUrl 格式的时候 preFiles 的写入顺序 并不是按照for循环的顺序

      对此我百思不得其解

      只能靠后期对 数组遍历来解决问题

      希望以后对js有了一些新的看法才来 更新一下

    最后

      我终于写完了

      当然这个只是一个开始

      还有后端的接收的地方,那一段代码 这个可以看我前面写的一些随笔 我懒得翻了

    Let it roll
  • 相关阅读:
    Git的搭建和使用技巧完整精华版
    Apache配置虚拟主机
    php curl向远程服务器上传文件
    将树形结构的数组按照顺序遍历为二维数组
    编码-截取中文-去除HTML字符
    PHP最原始的上传文件函数
    PHP中获取当前页面的完整URL
    ethereum/EIPs-191 Signed Data Standard
    ethereum/EIPs-607 Hardfork Meta: Spurious Dragon硬分叉相关
    ethereum/EIPs-155 Simple replay attack protection 35,36
  • 原文地址:https://www.cnblogs.com/WaterMealone/p/14409454.html
Copyright © 2020-2023  润新知