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="{ width: (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="{ width: 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="{ width: (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="{ width: 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   /* width: 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有了一些新的看法才来 更新一下

最后

  我终于写完了

  当然这个只是一个开始

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

 

posted @ 2021-02-17 19:04  WaterMealone  阅读(602)  评论(0编辑  收藏  举报