zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    leetcode Super Ugly Number
    leetcode Find Median from Data Stream
    leetcode Remove Invalid Parentheses
    leetcode Range Sum Query
    leetcode Range Sum Query
    leetcode Minimum Height Trees
    hdu 3836 Equivalent Sets
    hdu 1269 迷宫城堡
    hud 2586 How far away ?
    poj 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/WaterMealone/p/14409454.html
Copyright © 2011-2022 走看看