2/16 Vue 上传图片并预览的实现 ( 一 )

2021-02-19 01:20

阅读:573

标签:解决   机制   opacity   文件大小   drop   idt   value   src   nbsp   

写在前面

  现在还没有上传功能 只差个axios

  明天继续写

  今天先放个代码

  这个东西可以直接复制用

  但是上传的文件位置和渲染出来的不一样,估计是底层的东西问题,我没有解决方案 ( for 循环的机制 )

  技术图片 

  1 DOCTYPE html>
  2 html lang="zh-CN">
  3 
  4 head>
  5     meta charset="UTF-8">
  6     title>Documenttitle>
  7     script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">script>
  8     
  9     link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
 10 head>
 11 
 12 body>
 13     div id="app">
 14         div class="container">
 15 
 16             div class="title-container">
 17                 span>上传文件span>
 18             div>
 19 
 20             div class="upload-box">
 21                 div class="drag-box" ref="dragBox" :class="isDrag? ‘draging-drag-box‘:‘‘ ">
 22                     label>
 23                         div class="icon-container">
 24                             i class="fa fa-file" :class="isDrag? ‘draging-fa-file‘: ‘‘">i>
 25                         div>
 26                         div class="label-text-container">
 27                             span :class="isDrag? ‘draging-label-text-container‘:‘‘ ">请将文件拖动至此span>
 28                             br>
 29                             span :class="isDrag? ‘draging-label-text-container‘:‘‘ ">或者单击上传span>
 30                         div>
 31                         input type="file" accept="image/jepg, image/png" name="pictures"
 32                             @change="storepreFiles($event.target)" multiple>
 33                     label>
 34                 div>
 35 
 36                 div class="show-file-box" v-if=" files.length == 0 ? false : true">
 37 
 38                     div class="text-container">
 39                         span>上传列表span>
 40                         span>{{updateState}} / {{preFilesLength}}span>
 41                     div>
 42                     
 43                     div class="pre-upload-bar">
 44                         div>
 45                             span>列表加载进度 {{(updateState / preFilesLength).toFixed(1) *100}} %span>
 46                         div>
 47                         div class="pre-upload-bar-done"
 48                             :style="{ width: ( updateState / preFilesLength ) *100 + ‘%‘ }">
 49                         div>
 50                     div>
 51                     
 52 
 53                     ul class="pre-upload-list">
 54                         transition-group tag="li" name="list">
 55                             li class="pre-upload-file" v-for="file in preFiles" :key="file.name">
 56                                 div class="review">
 57                                     
 58                                     div class="review-image-container">
 59                                         img class="review-image" :src="file.src">
 60                                     div>
 61 
 62                                     div class="review-file-name-container">
 63                                         span class="file-name"> {{ file.name }}span>
 64                                     div>
 65                                     div class="progress">
 66                                         div class="progress-done" :style="{ width: file.index + ‘%‘ }">div>
 67                                     div>
 68                                     span class="percent">{{ file.index }}%span>
 69                                     input class="select-box" check type="checkbox" name="select" :value="file.name"
 70                                         :checked="file.isChecked" @change="doSelect(file.name)" ref="select" />
 71                                 div>
 72                             li>
 73                         transition-group>
 74                     ul>
 75 
 76 
 77                     hr color="lightpink" style="margin: 10px 8px;">
 78                     
 79                     div class="bottom-select">
 80                         span class="bottom-select-button" @click="seletAll">{{ select }}span>
 81                         div class="bottom-select-info">
 82                             div> span>已选span> span class="span-special"
 83                                     :style="{‘color‘:  showSize() > 15 ? ‘red‘:‘green‘}">{{showSelect()}} span>
 84                                 span>/{{preFilesLength}}span>
 85                             div>
 86                             div> span class="span-special" :style="{‘color‘:  showSize() > 15 ? ‘red‘:‘green‘}">{{
 87                                     showSize() }} span> span>/ {{showAllSize()}} mb span>div>
 88                         div>
 89                     div>
 90 
 91                     div class="bottom-upload">
 92                         span>上传span>
 93                     div>
 94 
 95 
 96                 div>
 97             div>
 98 
 99         div>
100 
101     div>
102 body>
103 
104 script>
105     var vm = new Vue({
106         el: #app,
107         data() {
108             return {
109                 // 预展示的图片对象数组
110                 preFiles: [],
111                 // preFiles: (function (num) {
112                 //     var temp = new Array
113                 //     for (let i = 0; i 
114                 //         temp.push(0)
115                 //     }
116                 //     return temp
117                 // })(9),
118 
119                 preFilesLength: 0,
120                 // 这个是渲染list的过程 渲染到第几个li
121                 updateState: 0,
122 
123                 // 真正要上传的图片文件
124                 files: [],
125 
126                 // 选择上传的文件
127                 select: "全选",
128 
129                 // 是否进行拖动事件
130                 isDrag: false
131             }
132         },
133         updated() {
134         },
135         mounted: function () {
136             var dragBox = this.$refs.dragBox;
137             dragBox.addEventListener(dragenter, this.onDrag, false);
138             dragBox.addEventListener(dragover, this.onDrag, false);
139             dragBox.addEventListener(dragleave, () => { this.isDrag = false; }, false);
140             dragBox.addEventListener(drop, this.onDrop, false);
141         },
142         watch: {
143             // 通过对 preFiles 监听 实现简单加载文件进度条
144             preFiles: {
145                 handler: updateS
146             }
147         },
148         methods: {
149             storepreFiles(obj) {
150                 // 获取input里面的文件组
151                 var fileList = obj.files;
152                 // 先判定有没有重复提交的文件 可以加判断条件
153                 for (let i = 0; i  fileList.length; i++) {
154                     for (let j = 0; j  this.preFiles.length; j++) {
155                         if (this.preFiles[j].name === fileList[i].name) {
156                             alert("有文件重复")
157                             return
158                         }
159                     }
160                 }
161 
162                 this.preFilesLength = this.preFilesLength + fileList.length
163 
164                 // 这样防止变成 两个Filelist 对象 组合
165                 for (var i = 0; i  fileList.length; i++) {
166                     this.files = this.files.concat(fileList[i])
167                 }
168                 var vue = this
169                 //对文件组进行遍历,可以到控制台打印出fileList去看看
170                 for (let i = 0; i  fileList.length; i++) {
171 
172                     function uploadFile(file) {
173                         return new Promise(function (resolve, reject) {
174                             let reader = new FileReader()
175                             reader.readAsDataURL(file)
176                             reader.onload = function () {
177                                 resolve(this.result)
178                             }
179                         })
180                     }
181                     uploadFile(fileList[i]).then(function (result) {
182                         console.group(i)
183                         console.log(event)
184                         console.log(fileList[i])
185                         console.groupEnd()
186                         // vue.preFiles.splice(i, 0, { name: fileList[i].name, size: fileList[i].size, index: 0, })
187                         vue.preFiles.push({ name: fileList[i].name, size: fileList[i].size, index: 0, src: result, isChecked: true })
188                     })
189                 }
190             },
191 
192             // 渲染列表的参数
193             updateS() {
194                 this.updateState = this.updateState + 1
195             },
196 
197             findPreFile(name) {
198                 let that = this
199                 return this.preFiles.find((item, index) => {
200                     return item.name === name;
201                 })
202 
203             },
204 
205             // 点击 选择框 和 全选
206             doSelect(name) {
207                 this.preFiles.forEach(element => {
208                     if (element.name == name) {
209                         element.isChecked = !element.isChecked
210                     }
211 
212                 });
213 
214             },
215             seletAll() {
216                 if (this.$refs.select.find(item => item.checked == false)) {
217                     console.log(this.$refs.select)
218                     this.preFiles.forEach(element => {
219                         element.isChecked = true
220                     })
221                 }
222 
223             },
224 
225             // 显示 选中个数 和 显示 选中的文件大小
226             showSelect() {
227                 let num = 0
228                 this.preFiles.forEach(element => {
229                     if (element.isChecked == true) {
230                         num++;
231                     }
232                 });
233                 return num
234             },
235 
236             showSize() {
237                 let size = 0
238                 this.preFiles.forEach(element => {
239                     if (element.isChecked == true) {
240                         size = size + element.size
241                     }
242                 });
243                 return (size / Math.pow(2, 20)).toFixed(2)
244             },
245 
246             showAllSize() {
247                 let size = 0
248                 this.preFiles.forEach(element => {
249 
250                     size = size + element.size
251                 });
252                 return (size / Math.pow(2, 20)).toFixed(2)
253 
254             },
255 
256             // 拖动文件上传
257             onDrag: function (e) {
258                 this.isDrag = true;
259                 e.stopPropagation();
260                 e.preventDefault();
261                 //    var dragBox =  this.$refs.dragBox;
262                 //    var faFile = this.$refs.faFile;
263                 //    var textContainer = this.$refs.textContainer;
264 
265                 //    dragBox.onmouseover();
266                 //    console.log(dragBox)
267 
268             },
269 
270             onDragLeave(e) {
271 
272             },
273 
274             onDrop: function (e) {
275                 this.isDrag = false;
276                 e.stopPropagation();
277                 e.preventDefault();
278                 var dt = e.dataTransfer;
279                 this.storepreFiles(dt);
280             }
281         }
282     });
283 
284 script>
285 
286 style>
287     span {
288         font-weight: 700;
289         font: bolder;
290     }
291 
292     .container {
293         width: 450px;
294         /* background-color: rgb(195, 209, 228); */
295         box-shadow: 2px 2px 2px 2px rgba(68, 68, 68, 0.2);
296         border-radius: 10px;
297         padding: 20px;
298     }
299 
300     .upload-box {
301         /* width: 400px; */
302         /* height: 400px; */
303 
304     }
305 
306     .title-container {
307         margin: 10px 8px 20px 8px;
308         font-size: 20px;
309 
310         border-radius: 5px;
311         background: linear-gradient(to right, rgb(112, 158, 242), rgb(255, 255, 255));
312         color: white;
313     }
314 
315     .drag-box {
316         padding: 20px;
317         margin: 10px auto;
318         width: 380px;
319         border-radius: 10px;
320         border: 5px dashed rgba(112, 155, 248, 0.7);
321         text-align: center;
322         transition: all linear 0.1s;
323     }
324 
325     .label-text-container {
326         margin: 20px 8px;
327         font-size: 20px;
328     }
329 
330     .text-container {
331         margin: 20px 8px;
332         font-size: 20px;
333         border-radius: 5px;
334         background: linear-gradient(to right, rgb(112, 158, 242), rgb(255, 255, 255));
335         color: white;
336     }
337 
338     .drag-box .label-text-container {
339         color: rgba(190, 190, 190, 0.8);
340         transition: all linear 0.1s;
341     }
342 
343     .icon-container {
344         margin: 15px;
345     }
346 
347     .fa-file {
348         color: rgba(247, 187, 219, 0.8);
349         font-size: 100px;
350         transition: all linear 0.1s;
351     }
352 
353     /*  当进入文件的时候添加css */
354     .drag-box:hover {
355         border: 5px dashed rgba(112, 155, 248, 1);
356     }
357 
358     .drag-box:hover .fa-file {
359         color: rgb(245, 124, 188);
360     }
361 
362     .drag-box:hover .label-text-container {
363         color: rgb(68, 68, 68);
364     }
365 
366 
367 
368     /*  当拖动文件的时候添加css */
369     .draging-drag-box {
370         border: 5px dashed rgba(112, 155, 248, 1);
371     }
372 
373     .draging-fa-file {
374         color: rgb(245, 124, 188);
375     }
376 
377     .draging-label-text-container {
378         color: rgb(68, 68, 68);
379     }
380 
381     /*  点击上传文件的时候的那个input */
382     label input {
383         display: none;
384     }
385 
386 
387     .review {
388         border: 1px solid transparent;
389         border-radius: 5px;
390         color: #777;
391         display: flex;
392         font-size: 12px;
393         align-items: center;
394         padding: 10px;
395         margin: 5px 8px;
396     }
397 
398     .review:hover {
399         cursor: pointer;
400         /* border: 1px solid #ddd; */
401         box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 0.7);
402     }
403 
404     .pre-upload-bar {
405         margin: 10px 10px;
406         height: 20px;
407     }
408 
409     .pre-upload-bar span {
410         font-size: 12px;
411         font-weight: 20px;
412         color: #777
413     }
414 
415     .pre-upload-bar-done {
416         background: linear-gradient(to left, rgb(112, 158, 242), rgb(119, 140, 255));
417         box-shadow: 0 3px 3px -5px rgb(100, 115, 143), rgb(134, 138, 165);
418         border-radius: 5px;
419         height: 3px;
420         width: 0;
421         transition: width ease 0.2s;
422     }
423 
424     .review-file-name-container {
425         width: 100px;
426     }
427 
428     .review-image-container {
429         margin: 0 8px 0 0;
430     }
431 
432     .review-image {
433         width: 50px;
434     }
435 
436     .pre-upload-list {
437         list-style: none;
438         /*  取消缩进 */
439         margin: 0px;
440         padding: 0px
441     }
442 
443     .file-name {
444         width: 100%;
445         float: left;
446         overflow: hidden;
447         text-overflow: ellipsis;
448         white-space: normal;
449     }
450 
451     .progress {
452         background-color: rgba(100, 100, 100, 0.2);
453         border-radius: 5px;
454         position: relative;
455         margin: 0 10px;
456         height: 10px;
457         width: 150px;
458     }
459 
460     .progress-done {
461         background: linear-gradient(to left, rgb(242, 112, 156), rgb(255, 148, 114));
462         box-shadow: 0 3px 3px -5px rgb(242, 112, 156), 0 2px 5px rgb(242, 112, 156);
463         border-radius: 5px;
464         height: 10px;
465         width: 0;
466         transition: width ease 0.1s;
467     }
468 
469     .select-box {
470         width: 20px;
471         height: 20px;
472         margin: 0 0 0 36px;
473     }
474 
475 
476     /* list的transition group */
477     .list-enter,
478     .list-leave-to {
479         opacity: 0;
480     }
481 
482     .list-enter-active {
483         animation: moveIn 1s;
484     }
485 
486     .list-leave-active {
487         animation: moveOut 1s;
488         /* transition: all 1s linear; */
489     }
490 
491     @keyframes moveIn {
492         0% {
493             opacity: 0;
494             transform: translate(30px, 15px);
495         }
496 
497         30% {
498             opacity: 0.5;&g


评论


亲,登录后才可以留言!