vue3點(diǎn)擊按鈕下載文件功能的代碼實(shí)現(xiàn)
VUE3實(shí)現(xiàn)點(diǎn)擊按鈕下載文件功能
在寫vue項(xiàng)目時(shí),有個(gè)需求是點(diǎn)擊表格中某一行的下載按鈕,然后開始下載這一行對(duì)應(yīng)的文件,效果如下:
表格每行的最右側(cè)的藍(lán)色按鈕就是點(diǎn)擊下載,這里涉及到原生的JavaScript寫法,長(zhǎng)期在寫vue項(xiàng)目,原生的寫法都很陌生了,記錄一下
先上組件的原始代碼:
<template> <BreadCrumb ref="breadCrumb" :item="item"></BreadCrumb> <div class="pane-content"> <div class="pane-top"> <div class="module-common-header"> <div class="button-wrapped"> <el-upload v-model:file-list="fileList" class="upload-demo" multiple :on-exceed="handleExceed" action="http://127.0.0.1:3088/api/files/uploadFile" :on-success="handleSuccess" :show-file-list="false"> <el-button type="primary">上傳文件</el-button> </el-upload> </div> </div> <div class="module-common-table"> <el-table :data="tableData" border style="width: 100%"> <el-table-column type="index" width="50"></el-table-column> <el-table-column show-overflow-tooltip v-for="(item, index) in tableLabel" :key="index" :prop="item.prop" :label="item.label" /> <el-table-column fixed="right" label="操作"> <template #default="scope"> <el-button type="primary" size="small" @click="downloadFile(scope.row)">下載文件</el-button> <el-popconfirm title="確定刪除該文件嗎?" confirm-button-text="是" cancel-button-text="否" @confirm="deleteFile(scope.row)"> <template #reference> <el-button type="danger" size="small">刪除文件</el-button> </template> </el-popconfirm> </template> </el-table-column> </el-table> </div> </div> <div class="table-footer"> <el-pagination :page-size="10" :pager-count="5" layout="prev, pager, next" :total="filesLength" :current-page="paginationData.currentPage" @current-change="currentPageChange" /> </div> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { getFilesLengthAPI, returnFileListDataAPI, bindFileAndUserAPI, deleteFileAPI, updateDownloadTimesAPI, } from '@/apis/files' const item = ref({ first: '合同管理', }) const tableData = ref([]) const tableLabel = [ { prop: 'file_name', label: '合同名' }, { prop: 'file_size', label: '合同文件大小' }, { prop: 'upload_person', label: '上傳人' }, { prop: 'download_number', label: '下載次數(shù)' }, { prop: 'upload_time', label: '上傳時(shí)間' }, // { prop: 'message_content', label: '消息內(nèi)容' }, ] const fileList = ref([]) // 上傳成功之后的回調(diào)函數(shù) const handleSuccess = async (response, uploadFile, uploadFiles) => { if (response.status == 0) { const name = JSON.parse(localStorage.user).userInfo.name const url = response.url const res = await bindFileAndUserAPI({ name, url }) if (res.status == 0) { ElMessage.success('上傳成功') getCurrentPageData() getFilesLength() } else ElMessage.error('上傳失敗') } else { ElMessage.error('上傳失敗,請(qǐng)檢查是否重名') } } // 超出文件個(gè)數(shù)限制的鉤子 const handleExceed = (uploadFile, uploadFiles) => { } // 下載文件 const downloadFile = async (row) => { // console.log(row) const { download_number, id } = row await updateDownloadTimesAPI({ download_number, id }) const url = row.file_url const link = document.createElement('a') link.href = url link.setAttribute('download', '') document.body.appendChild(link) link.click() document.body.removeChild(link) getCurrentPageData() } // 刪除文件 const deleteFile = async row => { const res = await deleteFileAPI({ id: row.id }) if (res.status == 0) ElMessage.success('刪除成功') else ElMessage.error('刪除失敗') getCurrentPageData() getFilesLength() } // 分頁(yè) const paginationData = ref({ // 總頁(yè)數(shù) pageCount: 1, // 當(dāng)前頁(yè) currentPage: 1, }) // 獲取數(shù)據(jù)總數(shù) const filesLength = ref(0) const getFilesLength = async () => { const res = await getFilesLengthAPI() filesLength.value = res.filesCount } // 獲取首頁(yè)數(shù)據(jù) const getFirstPageList = async () => { const res = await returnFileListDataAPI({ page: 1 - 1 }) res.forEach(item => { item.upload_time = item.upload_time?.slice(0, 19) item.file_size = Math.floor(item.file_size) + 'kb' }) tableData.value = res } // 頁(yè)碼切換 const currentPageChange = async (val) => { paginationData.value.currentPage = val const res = await returnFileListDataAPI({ page: val - 1 }) res.forEach(item => { item.upload_time = item.upload_time?.slice(0, 19) item.file_size = Math.floor(item.file_size) + 'kb' }) tableData.value = res } // 增刪數(shù)據(jù)后,需要刷新當(dāng)前頁(yè)數(shù)據(jù) const getCurrentPageData = async () => { const res = await returnFileListDataAPI({ page: paginationData.value.currentPage - 1 }) res.forEach(item => { item.upload_time = item.upload_time?.slice(0, 19) item.file_size = Math.floor(item.file_size) + 'kb' }) tableData.value = res } onMounted(() => { getFilesLength() getFirstPageList() }) </script> <style lang="scss" scoped> .pane-content { margin-top: 8px; display: flex; flex-direction: column; justify-content: space-between; height: calc(100vh - 118px); background: #fff; .pane-top { padding: 8px; background: #fff; .module-common-header { padding: 0 20px; display: flex; align-items: center; justify-content: flex-end; } .module-common-table { min-height: 10px; padding: 10px 20px 20px; margin-bottom: 8px; background: #fff; } } .table-footer { display: flex; justify-content: flex-end; margin-bottom: 8px; } } </style>
我用的是vue3+setup語法糖寫法,代碼比較長(zhǎng),關(guān)注一下與下載相關(guān)的代碼:
html部分
<el-table-column fixed="right" label="操作"> <template #default="scope"> <el-button type="primary" size="small" @click="downloadFile(scope.row)">下載文件</el-button> <el-popconfirm title="確定刪除該文件嗎?" confirm-button-text="是" cancel-button-text="否" @confirm="deleteFile(scope.row)"> <template #reference> <el-button type="danger" size="small">刪除文件</el-button> </template> </el-popconfirm> </template> </el-table-column>
其實(shí)就是表格最后一列,添加兩個(gè)按鈕,然后為這個(gè)按鈕傳入本行的所有數(shù)據(jù),下載文件按鈕添加點(diǎn)擊函數(shù)downloadFile,并傳入行數(shù)據(jù)作為參數(shù)
JavaScript部分
js部分是實(shí)現(xiàn)點(diǎn)擊下載的核心,看downloadFile方法
// 下載文件 const downloadFile = async (row) => { // console.log(row) const { download_number, id } = row // 從行中獲取下載文件接口的傳入?yún)?shù) await updateDownloadTimesAPI({ download_number, id }) // 調(diào)用下載文件的接口 const url = row.file_url // 從行數(shù)據(jù)中獲取下載鏈接 const link = document.createElement('a') // 創(chuàng)建鏈接標(biāo)簽,即a標(biāo)簽,并將dom命名為link link.href = url // 為dom為link的元素添加鏈接 link.setAttribute('download', '') // 為link設(shè)置下載屬性 document.body.appendChild(link) // 把創(chuàng)建并配置好的link dom添加到頁(yè)面文檔中 link.click() // 模擬dom的點(diǎn)擊事件 document.body.removeChild(link) // 從文檔中移出link節(jié)點(diǎn) getCurrentPageData() // 調(diào)用寫好的方法刷新數(shù)據(jù) }
相關(guān)的解釋我都寫在了上面的代碼中,其中下面兩個(gè)步驟不是必須的:
- await updateDownloadTimesAPI({ download_number, id }) ,點(diǎn)擊下載后,要在數(shù)據(jù)庫(kù)中標(biāo)記,增加點(diǎn)擊量
- getCurrentPageData(),因?yàn)椴僮髁藬?shù)據(jù)庫(kù),數(shù)據(jù)要更新,所以這是為了更新數(shù)據(jù)
以上就是vue3實(shí)現(xiàn)點(diǎn)擊按鈕下載文件功能的詳細(xì)內(nèi)容,更多關(guān)于vue3下載文件功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue集成高德地圖amap-jsapi-loader的實(shí)現(xiàn)
本文主要介紹了vue集成高德地圖amap-jsapi-loader的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06vue 基于abstract 路由模式 實(shí)現(xiàn)頁(yè)面內(nèi)嵌的示例代碼
這篇文章主要介紹了vue 基于abstract 路由模式 實(shí)現(xiàn)頁(yè)面內(nèi)嵌的示例代碼,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12Vue.js一個(gè)文件對(duì)應(yīng)一個(gè)組件實(shí)踐
Vue.js實(shí)現(xiàn)"一個(gè)文件對(duì)應(yīng)一個(gè)組件",無需webpack等工具,按需加載組件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10在Vue中實(shí)現(xiàn)父組件控制子組件的值的兩種方法
在Vue開發(fā)中,父組件和子組件之間的數(shù)據(jù)傳遞是一項(xiàng)常見的任務(wù),本文將介紹如何在Vue中實(shí)現(xiàn)父組件控制子組件的值,以便靈活地管理和更新子組件的數(shù)據(jù),文中有詳細(xì)的代碼講解,需要的朋友可以參考下2023-11-11Vue實(shí)現(xiàn)文字上下滾動(dòng)動(dòng)畫的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何使用Vue實(shí)現(xiàn)超酷文字上下滾動(dòng)動(dòng)畫,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2024-03-03