主頁 > 企業開發 > 前端檔案上傳的幾種互動造輪子

前端檔案上傳的幾種互動造輪子

2023-06-28 10:03:59 企業開發

背景

前端檔案上傳本來是一個常規互動操作,沒什么特殊性可言,但是最近在做檔案上傳,需要實作截圖粘貼上傳,去找了下有沒有什么好用的組件,網上提供的方法有,但是沒找完整的組件來支持cv上傳,經過了解發現可以用剪貼板功能讓自己的cv實作檔案上傳,于是自己就整合了目前幾種檔案上傳的互動方式,碼了一個支持cv的vue3檔案上傳組件(造個輪子),

介紹

作為一個完整的組件內容還是挺多的,這里主要介紹下上傳互動中一些主要功能,包括上傳的幾種互動方式,

上傳進度的獲取,上傳型別的限制,默認上傳請求和自定義上傳請求,

以下代碼都是非完整代碼,大家用于參考實作程序,可以通過以下代碼修改來完成自己想要的互動功能,

幾種互動

1,點擊選擇上傳

點擊選擇是最常見的上傳互動,之前原生上傳控制元件,樣式修改比較麻煩,為了修改上傳樣式,我們可以把該控制元件設定隱藏,用其他元素通過從click互動, 來觸發該檔案選擇控制元件,在選擇檔案控制元件上系結onchange事件,該控制元件在change后獲取到檔案,然后呼叫上傳方法,實作如下:

<div  @click="handleClick">
     <input ref="inputRef" 
           
          :name="name" :multiple="multiple" 
          :accept="accept" type="file"
          @change="handleChange" />
</div>
<script setup>
    const inputRef = shallowRef(null)
    const handleClick = () => {
        inputRef.value.valuehttps://www.cnblogs.com/Jcloud/archive/2023/06/27/= ''
        inputRef.value?.click()
    }
    const handleChange = (e) => {
        const files = e.target.files
        if (!files) return
        // 獲取到檔案后呼叫附件上傳方法
        uploadFiles(files)
    }
</script>
<style  lang='less' scoped>
    .uploader-target {
        display: none;
    }
</style>

2,拖動上傳

拖拽檔案上傳,首先在頁面上建立一個拖放區域,在拖放區域上系結拖放事件,監聽拖放事件drop內容中datTransfer中是包含files,如果存在files,獲取files然后呼叫上傳附件方法,

拖放區域可以通過事件dragover來檢查拖放檔案是否進入拖放區域來設定拖放區域懸浮樣式,通過dragleave來檢查離開拖放區取消懸浮樣式,

進行互動提示

實作如下:

<div  v-if="props.uploadMode == 'drag'" : @drop.prevent="onDrop" @dragover.prevent="onDragover"
     @dragleave.prevent="dragover = false">
     <div >
         <span>+</span>
     </div>
  </div>
<script setup>
const dragover = ref(false)
const onDrop = (e) => {
        const files = Array.from(e.dataTransfer?.files)
        dragover.value = https://www.cnblogs.com/Jcloud/archive/2023/06/27/false
        uploadFiles(files);
    }
const onDragover = () => {
        dragover.value = true
    }
</script>

3,復制上傳(復制檢測區域設定)

復制上傳的互動步驟

?將檔案保存到剪貼板: 執行鍵盤快捷鍵或者使用滑鼠復制

?將滑鼠移動到可粘貼區: 判斷是否移動到可粘貼區,來確定是否在執行粘貼后上傳,否則整個頁面都會作為粘貼區,

?執行粘貼操作:執行鍵盤粘貼快捷鍵(ctrl+v)

粘貼區系結paste事件,在觸發paste事件前將滑鼠移到粘貼區,復制會被檢查不在粘貼區,阻止上傳操作,實作如下:

<div  
     v-if="props.uploadMode == 'paste'" 
     : 
     @mouseover.stop="clipboardover = true"
     @mouseleave.stop="clipboardover = false"
     @drop.prevent="onDrop" 
     @dragover.prevent="onDragover"
     @dragleave.prevent="dragover = false"
     @paste="pasteFun"
 >
     <!--默認插槽內容-->
     <template v-if="$slots.default == null">
         <div >
             <span>+</span>
         </div>
     </template>
     <slot />
 </div>
<script setup>
  const  clipboardover = ref(false)
  const pasteFun = (e) => {
      if(!clipboardover.value) return
      const clipboardFile = e.clipboardData.files;
      uploadFiles(clipboardFile)
 }
</script>

上傳模式

根據以上三種互動,大家可自由組合上傳形式,比如點擊和拖拽,拖拽和粘貼組合等等,我這邊目前按點擊,拖拽,粘貼疊加組合,設定為:

?點擊上傳,click

?拖拽上傳 drag(包括點擊上傳和拖拽上傳)

?粘貼上傳 paste (包括點擊,拖拽和復制上傳)

通過傳參 uploadeMode設定 (click, drag, paste)

組件設定:

<div  @click="handleClick">
    <input 
        ref="inputRef" 
         
        :name="name" 
        :multiple="multiple" 
        :accept="props.accept" 
        type="file"
        @change="handleChange" 
        v-if="props.uploadMode != 'click'"
    />
   <!-- click -->
   <div  v-if="props.uploadMode == 'click'">
        <slot />
        <input 
            ref="inputRef" 
             
            :name="name" 
            :multiple="multiple" 
            :accept="accept" 
            type="file"
            @change="handleChange" 
            @click.stop />
    </div>
    <!-- drag -->
    <div  
        v-if="props.uploadMode == 'drag'" 
        : 
        @drop.prevent="onDrop" 
        @dragover.prevent="onDragover"
        @dragleave.prevent="dragover = false">
         <template v-if="$slots.default == null">
             <div >
                 <span>+</span>
              </div>
          </template>
          <slot />
     </div>
     <!-- copy -->
     <div  
          v-if="props.uploadMode == 'paste'" 
          : 
          @mouseover.stop="clipboardover = true"
          @mouseleave.stop="clipboardover = false"
          @drop.prevent="onDrop" 
          @dragover.prevent="onDragover"
          @dragleave.prevent="dragover = false"
          @paste="pasteFun"
       >
          <template v-if="$slots.default == null">
              <div >
                 <span>+</span>
               </div>
          </template>
          <slot />
        </div>
    </div>
</template>

組件應用

<Upload action="https://jsonplaceholder.typicode.com/posts/" uploadMode="click">
    <div>點擊上傳</div>
</Upload>
<script lang="ts">
    import Upload from '@/components/uploader';
</script>

檔案限制

檔案限制包括是否多檔案上傳限制multiple, 上傳數量limit限制,上傳型別accept限制,這些設定參考了element-plus上傳組件,在其基礎上做了簡化,實作如下

multiple 和 accept 首先需要在點擊控制元件上系結,以便于在點擊選擇上傳時就能夠過濾對應檔案,拖拽上傳和粘貼上傳,無法通過input[type=file] 組件控制需要在上傳方法中判斷過濾,(以粘貼上傳為例)

組件實作

<div  @click="handleClick">
        <input ref="inputRef" 
                
               :name="name" :multiple="multiple" :accept="props.accept" type="file"
                @change="handleChange" v-if="props.uploadMode != 'click'" @click.stop />

        <div  v-if="props.uploadMode == 'paste'" : 
            @mouseover.stop="clipboardover = true"
            @mouseleave.stop="clipboardover = false"
            @drop.prevent="onDrop" 
            @dragover.prevent="onDragover"
            @dragleave.prevent="dragover = false"
            @paste="pasteFun"
            >
            <template v-if="$slots.default == null">
                <div >
                    <span>+</span>
                </div>
            </template>
            <slot />
        </div>
    </div>
<script setup>
    import { shallowRef, ref } from 'vue';
    const inputRef = shallowRef(null)
    // 上傳檔案
    const uploadFiles = (files) => {
        if (files.length === 0) return
        const { limit, multiple, accept } = props
        // 是否多檔案限制,主要用于拖拽和粘貼上傳中
        if (!multiple) {
            files = Array.from(files).slice(0, 1)
        }
        // 檔案數量
        if (limit && files.length > limit) {
            /*具體大家需要的邏輯可自行定義*/
            return
        }
        // 檔案型別限制
        if (accept) {
            files = filesFiltered(Array.from(files), accept)
        }
        //在檔案符合條件后執行上傳方法
    }
    // 檔案過濾
    const filesFiltered = (files, accept) => {
        return files.filter((file) => {
            const { type, name } = file
            const extension = name.includes('.') ? `.${name.split('.').pop()}` : ''
            const baseType = type.replace(//.*$/, '')
            return accept
                .split(',')
                .map((type) => type.trim())
                .filter((type) => type)
                .some((acceptedType) => {
                    if (acceptedType.startsWith('.')) {
                        return extension === acceptedType
                    }
                    if (//*$/.test(acceptedType)) {
                        return baseType === acceptedType.replace(//*$/, '')
                    }
                    if (/^[^/]+/[^/]+$/.test(acceptedType)) {
                         type === acceptedType
                    }
                    return false
             })
        })
    }

</script>

上傳進度設定

獲取檔案上傳進度,使用ajax中的progress 事件監聽機制,回傳資料loaded進度,和ttotal進行計算,獲取到計算的百分比通過process插槽線上在界面上,

具體實作如下:

組件實作

檔案限制后執行組件上傳,默認情況下走內置的上傳方法,如果做了自定義,上傳進度也需要自己實作(自己實作程序可以參考內置方法中的實作)

// 上傳方法呼叫
ajaxUpload({...props, file})
// 上傳方法實作
ajaxUpload = (options) => {
const xhr = new XMLHttpRequest()
    const action = option.action
    console.log(xhr, xhr.upload)
    if (xhr.upload) {
    // 建立progress監聽
      xhr.upload.addEventListener('progress', (evt:any) => {
        const progressEvt = evt
        progressEvt.percent = evt.total > 0 ? (evt.loaded / evt.total) * 100 : 0
        // 回傳進度資料
        option.onProgress(progressEvt)
      })
    }
}

同樣檔案上傳成功,例外等方法也可以通過監聽load并且判斷 xhr.status 來實作,

xhr.addEventListener('load', () => {
      if (xhr.status < 200 || xhr.status >= 300) {
        return option.onError(getError(action, option, xhr))
      }
      option.onSuccess(getBody(xhr))
})

組件使用

?配置獲取進度資料回呼函式 onProgress

?配置接識訓傳的進度資料進行賦值

?配置進度條插槽顯示進度資料

<Upload action="https://jsonplaceholder.typicode.com/posts/" :limit="3" uploadMode="click" :onProgress="progress">
   <div >點擊上傳</div>
   <template v-slot:progress>
       <!-自定義的進度條樣式,大家可以根據自己的想象,自行設定進度條樣式-->
       <div >
          <div >
             <span  :style="{'width': progressval + '%'}"></span>
           </div>
           <span >{{progressval}} %</span>
        </div>
   </template>
</Upload>
<script setup>
import {ref} from 'vue'
import Upload from '@/components/uploader';
const progressval = ref(0)
const progress = (evt)=>{
      progressval.value = https://www.cnblogs.com/Jcloud/archive/2023/06/27/evt.percent.toFixed(2)
},
// 上傳成功
const uploadSucess = (e)=>{
      console.log('sucess', e)
}
// 上傳例外
const uploadError= (e)=> {
   console.log('sucess', e)
}
</script>

自定義上傳請求

默認情況下,不需要自定義上傳請求,組件內置了上傳請求,如果個人有需求可以自定義上傳請求,子定義上傳請求,是在檔案限制流程后,檢查是否有自定義請求方法,如果存在就將檔案傳入自定義請求方法,

組件實作:

// 上傳檔案
const uploadFiles = (files) => {
    if (files.length === 0) return
    const { limit, multiple, accept, httpRequest } = props
    // 是否多檔案限制,主要用于拖拽和粘貼上傳中
    if (!multiple) {
       files = Array.from(files).slice(0, 1)
    }
    // 檔案數量
    if (limit && files.length > limit) {
       /*具體大家需要的邏輯可自行定義*/
       return
    }
    // 檔案型別限制
    if (accept) {
       files = filesFiltered(Array.from(files), accept)
    }
    //在檔案符合條件后執行上傳方法
    // 自定義上傳方法呼叫
    if(httpRequest) {
       return httpRequest(files)
    }
 }

組件應用:

注意點: 通過自定義上傳方法實作時,在原來組件上的屬性action無效

<Upload :limit="3" uploadMode="click" :onProgress="progress" :onSuccess="uploadSucess" :onError="uploadError" :httpRequest="httpRequest">
    <div >點擊上傳</div>
    <template v-slot:progress>
       <div >
          <div >
              <span  :style="{'width': progressval + '%'}"></span>
           </div>
           <span >{{progressval}} %</span>
       </div>
    </template>
 </Upload>
<script setup>
   const httpRequest = (files)=> {
      // 獲取到檔案 ,自定已上傳方法
   }
</script>

總結

通過以上可以實作一個支持多種互動方式的檔案上傳組件,同時也將element-plus中檔案上傳的流程做了一個學習,因為該組件的實作程序就是參考了element-plus的實作,在element-plus上傳的基礎上添加了粘貼上傳互動, 該組件的實作重在互動方式,各個樣式風格通過插槽自定義,

作者:京東物流 劉海鼎

來源:京東云開發者社區

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556155.html

標籤:其他

上一篇:記錄--Threejs-著色器實作一個水波紋

下一篇:返回列表

標籤雲
其他(161755) Python(38255) JavaScript(25515) Java(18266) C(15238) 區塊鏈(8273) C#(7972) AI(7469) 爪哇(7425) MySQL(7270) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4607) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2437) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1985) HtmlCss(1976) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 前端檔案上傳的幾種互動造輪子

    前端檔案上傳本來是一個常規互動操作,沒什么特殊性可言,但是最近在做檔案上傳,需要實作截圖粘貼上傳,去找了下有沒有什么好用的組件,網上提供的方法有,但是沒找完整的組件來支持cv上傳,經過了解發現可以用剪貼板功能讓自己的cv實作檔案上傳,于是自己就整合了目前幾種檔案上傳的互動方式,碼了一個支持cv的vu... ......

    uj5u.com 2023-06-28 10:03:59 more
  • 記錄--Threejs-著色器實作一個水波紋

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 hree.js 是一個基于 WebGL 的 JavaScript 3D 庫,用于創建和渲染 3D 圖形場景。 一、 影像渲染程序 1、webGL webGL: WebGL 是一種基于 JavaScript API 的圖形庫,它允許在瀏覽器 ......

    uj5u.com 2023-06-28 09:58:41 more
  • CSS實作根據子元素數量應用不同樣式

    theme: condensed-night-purple highlight: atelier-cave-light 在前端的頁面布局中經常會出現在子元素個數使用不同的樣式的需求,比如文章串列,在較少內容下單串列現,而在元素內容較多時使用雙串列現。再比如在頁面排版上,可以根據元素內容的多少來修改內 ......

    uj5u.com 2023-06-28 09:57:34 more
  • 618技術揭秘:探究競速榜頁面核心前端技術

    本文將探究京東競速榜H5頁面的核心前端技術,包括影片、樣式配置化、皮膚切換、海報技術、除錯技巧等方面,希望能夠為廣大前端開發者提供一些有用的參考和思路。 ......

    uj5u.com 2023-06-28 09:57:04 more
  • CSS實作根據子元素數量應用不同樣式

    theme: condensed-night-purple highlight: atelier-cave-light 在前端的頁面布局中經常會出現在子元素個數使用不同的樣式的需求,比如文章串列,在較少內容下單串列現,而在元素內容較多時使用雙串列現。再比如在頁面排版上,可以根據元素內容的多少來修改內 ......

    uj5u.com 2023-06-28 09:56:39 more
  • 前端Vue自定義加載中loading加載結束end組件 可用于分頁展示 頁

    #### 前端Vue自定義加載中loading加載結束end組件 可用于分頁展示 頁面加載請求, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13219 #### 效果圖如下: ![](https://p3-juejin.byteimg. ......

    uj5u.com 2023-06-27 10:04:55 more
  • 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼

    #### 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼登錄模版 密碼登錄模版, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13221 #### 效果圖如下: #### ![](https://p3-juejin. ......

    uj5u.com 2023-06-27 10:04:49 more
  • 前端Vue自定義發送短信驗證碼彈框popup 實作剩余秒數計數 重發短

    前端Vue自定義發送短信驗證碼彈框popup 實作剩余秒數計數 重發短信驗證碼, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13207 效果圖如下: ![](https://p3-juejin.byteimg.com/tos-cn-i- ......

    uj5u.com 2023-06-27 10:04:45 more
  • 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼

    #### 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼登錄模版 密碼登錄模版, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13221 #### 效果圖如下: #### ![](https://p3-juejin. ......

    uj5u.com 2023-06-27 10:04:15 more
  • 驅動開發:內核讀寫記憶體多級偏移

    讓我們繼續在`《內核讀寫記憶體浮點數》`的基礎之上做一個簡單的延申,如何實作多級偏移讀寫,其實很簡單,讀寫函式無需改變,只是在讀寫之前提前做好計算作業,以此來得到一個記憶體偏移值,并通過呼叫記憶體寫入原函式實作寫出資料的目的。以讀取偏移記憶體為例,如下代碼同樣來源于本人的`LyMemory`讀寫驅動專案,其... ......

    uj5u.com 2023-06-27 09:58:39 more