前端解析包含圖片的excel文件完整步驟及代碼示例
一、前言
1、問(wèn)題描述
有時(shí)候難免會(huì)遇到解析excel的情況,現(xiàn)在前端的很多插件都可以實(shí)現(xiàn)excel文件中文本內(nèi)容的解析;但是很多時(shí)候excel文件中是帶有圖片文件的,這個(gè)圖片文件的提取著實(shí)是讓人有點(diǎn)頭疼的;
本人查閱了很多資料,試了很多方法,結(jié)果都是以失敗告終!
現(xiàn)決定使用一個(gè)迂回戰(zhàn)術(shù),完成一次曲線救國(guó),哈哈哈,方法可能不太好,但勉強(qiáng)能夠使用,如果有哪位大佬看見(jiàn),還望指點(diǎn)迷津,跪謝~
2、excel文件
3、實(shí)現(xiàn)效果
二、實(shí)現(xiàn)思路
- 第一步,使用XLSX插件,解析excel中的文本內(nèi)容;
- 第二步,使用JSZip插件,解析excel中的圖片內(nèi)容;
- 第三步,將圖片數(shù)據(jù)和文本數(shù)據(jù)進(jìn)行整理,封裝成我們最終需要的數(shù)據(jù)格式;
三、完整代碼
<template> <div class="container"> <!-- 長(zhǎng)傳組件 --> <el-upload action="" :before-upload="beforeUpload" :http-request="() => {}"> <el-button type="primary">導(dǎo)入excel</el-button> </el-upload> <!-- 表格組件 --> <el-table :data="tableData" border style="width: auto; margin-top: 10px"> <el-table-column :prop="item" :label="item" align="center" v-for="(item, index) in tableColumnLabel" :key="index" > <template #default="scope" v-if="item == 'avatar'"> <img :src="scope.row.avatar" alt="" style="width: 200px" /> </template> </el-table-column> </el-table> </div> </template> <script setup> import { ref } from "vue"; import JSZip from "jszip"; // 引入jszip import * as XLSX from "xlsx"; // 引入xlsx const tableColumnLabel = ref([]); // 獲取表頭內(nèi)容 const tableData = ref([]); // 表格數(shù)據(jù) const imageList = ref([]); // 表格圖片 // 加載按鈕的回調(diào) async function beforeUpload(file) { // 解析圖片 imageList.value = await getExcelImage(file); // 解析數(shù)據(jù) getExcelData(file); } // 解析數(shù)據(jù) function getExcelData(file) { let fileReader = new FileReader(); // 構(gòu)建fileReader對(duì)象 fileReader.readAsArrayBuffer(file); // 讀取指定文件內(nèi)容 // 讀取操作完成時(shí) fileReader.onload = function (e) { try { let data = e.target.result; // 取得數(shù)據(jù)data // console.log(data); let workbook = XLSX.read(data, { type: "binary" }); // 將data轉(zhuǎn)換成excel工作表數(shù)據(jù) // console.log("Excel工作簿", workbook); const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 獲取第一個(gè)工作表 // console.log("第一張工作表", worksheet); /* * XLSX.utils.sheet_to_json 輸出JSON格式數(shù)據(jù) * 獲取指定工作表中的數(shù)據(jù)sheetlist[],整個(gè)表中的數(shù)據(jù)存放在一個(gè)數(shù)組sheetlist中; * sheetlist數(shù)組中的每個(gè)元素均為一個(gè)數(shù)組rowlist,是每一行的數(shù)據(jù); */ const sheetlist = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); //console.log('sheetlist', sheetlist); // 封裝數(shù)據(jù) formatDate(sheetlist); } catch (e) { console.log("文件類型不正確"); return; } }; } // 封裝數(shù)據(jù) function formatDate(sheetlist) { try { if (sheetlist.length < 1) return; tableColumnLabel.value = sheetlist[0]; // 獲取表格列名 for (let i = 0; i < sheetlist.length - 1; i++) { // 這里length-1是因?yàn)槲覀兊膕heetlist[0]為列名,實(shí)際的數(shù)據(jù)要少 1; let obj = {}; for (let j = 0; j < sheetlist[0].length; j++) { // 頭像列,則取解析到的imageList中的相應(yīng)值; // 這里要求我們知道excel中存放圖片的列名,否則會(huì)導(dǎo)致讀取失??; if (sheetlist[0][j] == "avatar") { obj[sheetlist[0][j]] = `data:image/png;base64,${imageList.value[i]}`; // 注意base64編碼的處理 } else { // 非頭像列,直接取值; obj[sheetlist[0][j]] = sheetlist[i + 1][j] ?? ""; } } // console.log(obj); tableData.value.push(obj); // 添加到el-table綁定的數(shù)據(jù)源中 } console.log("tableData.value", tableData.value); } catch (error) { console.log(error); return; } } // 獲取圖片 async function getExcelImage(file) { // console.log(file); let imageList = []; // 用來(lái)存放圖片 const zip = new JSZip(); // 創(chuàng)建jszip實(shí)例 try { let zipLoadResult = await zip.loadAsync(file); // 將xlsx文件轉(zhuǎn)zip文件 // console.log("zipLoadResult", zipLoadResult); for (const key in zipLoadResult["files"]) { // 遍歷結(jié)果中的files對(duì)象 if (key.indexOf("media/image") != -1 && !key.dir) { await zip .file(zipLoadResult["files"][key].name) .async("base64") .then((res) => { imageList.push(res); // 將解析出的圖片的base64編碼值 先存入imageList數(shù)組中; }); } } } catch (error) { console.log(error); } // console.log('imageList', imageList); return imageList; } </script> <style lang="scss" scoped> </style>
四、準(zhǔn)備工作
1、excel文件
先準(zhǔn)備一個(gè)test.xlsx文件,內(nèi)容如下圖所示,主要帶上圖片就行;
2、上傳組件
添加一個(gè)上傳組件,用來(lái)上傳excel文件;這里采用的是element-plus中的el-upload組件;
<el-upload action="" :before-upload="beforeUpload" :http-request="() => {}"> <el-button type="primary">導(dǎo)入excel</el-button> </el-upload>
這個(gè)上傳組件并不是用來(lái)做上傳,只是利用它來(lái)讀取我們的excel文件;
后續(xù)我們將在beforeUpload()方法中處理導(dǎo)入的excel文件;
3、展示組件
添加一個(gè)數(shù)據(jù)展示組件,用來(lái)展示我們解析好的數(shù)據(jù);這里采用的是el-table組件;
注意這里的列是動(dòng)態(tài)生成的,如果是圖片的列,則添加img標(biāo)簽顯示圖片;
<el-table :data="tableData" border style="width: auto; margin-top: 10px"> <el-table-column :prop="item" :label="item" align="center" v-for="(item, index) in tableColumnLabel" :key="index"> <template #default="scope" v-if="item == 'avatar'"> <img :src="scope.row.avatar" alt="" style="width: 200px" /> </template> </el-table-column> </el-table>
表格需要用到的數(shù)據(jù);
import { ref } from "vue"; const tableColumnLabel = ref([]); // 獲取表頭內(nèi)容 const tableData = ref([]); // 表格數(shù)據(jù) const imageList = ref([]); // 表格圖片
4、安裝依賴
安裝jszip依賴;
npm install jszip 或 yarn add jszip
安裝xlsx依賴;
npm install xlsx 或 yarn xlsx
5、引入插件
在頁(yè)面中引入需要用的jszip和xlsx兩個(gè)依賴,可以使用其中的一些方法解析excel文件;
import JSZip from "jszip"; import * as XLSX from "xlsx";
6、現(xiàn)有效果
到此,準(zhǔn)備工作完成,現(xiàn)有代碼與頁(yè)面效果如下所示:
<template> <div class="container"> <!-- 長(zhǎng)傳組件 --> <el-upload action="" :before-upload="beforeUpload" :http-request="() => {}"> <el-button type="primary">導(dǎo)入excel</el-button> </el-upload> <!-- 表格組件 --> <el-table :data="tableData" border style="width: auto; margin-top: 10px"> <el-table-column :prop="item" :label="item" align="center" v-for="(item, index) in tableColumnLabel" :key="index"> <template #default="scope" v-if="item == 'avatar'"> <img :src="scope.row.avatar" alt="" style="width: 200px" /> </template> </el-table-column> </el-table> </div> </template> <script setup> import { ref } from "vue"; import JSZip from "jszip"; // 引入jszip import * as XLSX from "xlsx"; // 引入xlsx const tableColumnLabel = ref([]); // 獲取表頭內(nèi)容 const tableData = ref([]); // 表格數(shù)據(jù) const imageList = ref([]); // 表格圖片 // 加載按鈕的回調(diào) function beforeUpload(file){ console.log(file); } </script> <style lang="scss" scoped> </style>
可以在頁(yè)面看到一個(gè)導(dǎo)入按鈕和一個(gè)沒(méi)有任何數(shù)據(jù)的表格;
五、實(shí)現(xiàn)過(guò)程
1、加載excel
點(diǎn)擊導(dǎo)入excel按鈕,選擇我們之前準(zhǔn)備好的測(cè)試excel【test.xlsx】文件,
導(dǎo)入按鈕的回調(diào):
可以在控制臺(tái)查看打印輸出的結(jié)果:
到這里呢,表示我們的excel已經(jīng)加載成功了,接下來(lái)繼續(xù)解析讀取到的內(nèi)容即可;
2、解析圖片文件
(1)解析思路
- 使用jszip將xlsx文件轉(zhuǎn)成zip文件;
- 獲取zip文件中的圖片內(nèi)容;
- 將圖片信息轉(zhuǎn)base64編碼存儲(chǔ);
解析圖片文件我們需要用到j(luò)szip這個(gè)插件,至于為什么呢?因?yàn)槲易约涸嚵似渌姆椒ǘ紱](méi)有成功;
首先,我們先將【test.xlsx】轉(zhuǎn)成【test.zip】文件;這里復(fù)制一份文件后 直接修改文件擴(kuò)展名;壓縮是看不到效果的;
點(diǎn)開這個(gè)【test.zip】文件,可以看到以下內(nèi)容,
打開這個(gè)【xl】文件夾,在【media】下存放的是圖片文件,worksheets下存放的是文本文件;
所以,我們想要獲取excel中的圖片文件,只需訪問(wèn)這個(gè)zip文件,然后獲取其中【media】文件夾中的內(nèi)容即可;
這個(gè)zip文件只是簡(jiǎn)單查看,有助于我們理解的,并沒(méi)有解析的實(shí)際作用,后續(xù)刪除即可;
(2)解析過(guò)程
在beforeUpload()回調(diào)函數(shù)中,編寫解析代碼;
// 加載按鈕的回調(diào) async function beforeUpload(file){ // console.log(file); let imageList = []; // 用來(lái)存放圖片 const zip = new JSZip(); // 創(chuàng)建jszip實(shí)例 try { let zipLoadResult = await zip.loadAsync(file); // 將xlsx文件轉(zhuǎn)zip文件 console.log("zipLoadResult", zipLoadResult); // ...... } catch (error) { console.log(error); } return imageList; }
在打印輸出的結(jié)果中,我們可以看到跟之前自行手動(dòng)轉(zhuǎn)zip后的結(jié)果是一致的;圖片文件在【xl/media】 路徑文件夾中;
繼續(xù)解析獲取到的files對(duì)象,
// 加載按鈕的回調(diào) async function beforeUpload(file){ // console.log(file); let imageList = []; // 用來(lái)存放圖片 const zip = new JSZip(); // 創(chuàng)建jszip實(shí)例 try { let zipLoadResult = await zip.loadAsync(file); // 將xlsx文件轉(zhuǎn)zip文件 // console.log("zipLoadResult", zipLoadResult); for (const key in zipLoadResult["files"]) { // 遍歷結(jié)果中的files對(duì)象 if (key.indexOf("media/image") != -1 && !key.dir) { await zip .file(zipLoadResult["files"][key].name) .async("base64") .then((res) => { imageList.push(res); // 將解析出的圖片的base64編碼值 先存入imageList數(shù)組中; }); } } } catch (error) { console.log(error); } console.log('imageList', imageList); return imageList; }
可以看到已經(jīng)成功獲取到了兩個(gè)圖片的base64編碼值;
在下方鏈接中,可以檢測(cè)取到的bae64是否正確:
到此,我們已經(jīng)取到了excel文件中的圖片信息imageList??!
最后,我們將這段解析excel中圖片的代碼進(jìn)行封裝,后續(xù)在其他地方也可以使用;
// 加載按鈕的回調(diào) async function beforeUpload(file){ // 解析圖片 imageList.value = await getExcelImage(file); } // 獲取圖片 async function getExcelImage(file){ // console.log(file); let imageList = []; // 用來(lái)存放圖片 const zip = new JSZip(); // 創(chuàng)建jszip實(shí)例 try { let zipLoadResult = await zip.loadAsync(file); // 將xlsx文件轉(zhuǎn)zip文件 // console.log("zipLoadResult", zipLoadResult); for (const key in zipLoadResult["files"]) { // 遍歷結(jié)果中的files對(duì)象 if (key.indexOf("media/image") != -1 && !key.dir) { await zip .file(zipLoadResult["files"][key].name) .async("base64") .then((res) => { imageList.push(res); // 將解析出的圖片的base64編碼值 先存入imageList數(shù)組中; }); } } } catch (error) { console.log(error); } // console.log('imageList', imageList); return imageList; }
3、解析文本內(nèi)容
(1)解析思路
- 使用FileReader對(duì)象來(lái)讀取excel文件數(shù)據(jù)data;
- 使用xlsx獲取excel表格數(shù)據(jù);
- 封裝sheetlist數(shù)據(jù)為el-table綁定的數(shù)據(jù)格式;
(2)解析過(guò)程
首先,查看FileReader的讀取結(jié)果;
async function beforeUpload(file){ // 解析圖片 imageList.value = await getExcelImage(file); // ==================================================================================== // // 解析數(shù)據(jù) let fileReader = new FileReader(); // 構(gòu)建fileReader對(duì)象 fileReader.readAsArrayBuffer(file); // 讀取指定文件內(nèi)容 // 讀取操作完成時(shí) fileReader.onload = function (e) { try { console.log('data', e); // ...... } catch (e) { console.log("文件類型不正確"); return; } }; }
其次,使用XLSX.utils.sheet_to_json(worksheet, { header: 1 })方法,處理FileReader讀取到的數(shù)據(jù)data;
該方法的第一個(gè)參數(shù)woksheet是必須要傳的,值為工作表數(shù)據(jù);
第二個(gè)參數(shù)可選,用于指定輸出excel的格式;
// 加載按鈕的回調(diào) async function beforeUpload(file){ // 解析圖片 imageList.value = await getExcelImage(file); // ==================================================================================== // // 解析數(shù)據(jù) let fileReader = new FileReader(); // 構(gòu)建fileReader對(duì)象 fileReader.readAsArrayBuffer(file); // 讀取指定文件內(nèi)容 // 讀取操作完成時(shí) fileReader.onload = function (e) { try { let data = e.target.result; // 取得數(shù)據(jù)data // console.log(data); let workbook = XLSX.read(data, { type: "binary" }); // 將data轉(zhuǎn)換成excel工作表數(shù)據(jù) // console.log("Excel工作簿", workbook); const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 獲取第一個(gè)工作表 // console.log("第一張工作表", worksheet); /* * XLSX.utils.sheet_to_json 輸出JSON格式數(shù)據(jù) * 獲取指定工作表中的數(shù)據(jù)sheetlist[],整個(gè)表中的數(shù)據(jù)存放在一個(gè)數(shù)組sheetlist中; * sheetlist數(shù)組中的每個(gè)元素均為一個(gè)數(shù)組rowlist,是每一行的數(shù)據(jù); */ const sheetlist = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); console.log(sheetlist,'sheetlist'); } catch (e) { console.log("文件類型不正確"); return; } }; }
到此為止,我們已經(jīng)獲取到了excel中的文本數(shù)據(jù)sheetlist,可以在控制臺(tái)查看如下所示結(jié)果;
外層是一個(gè)數(shù)組[ ],存放整個(gè)excel中的文本數(shù)據(jù);
其中的每個(gè)元素均為一個(gè)數(shù)組[ ],存放的是每一行的數(shù)據(jù);
最后,我們將這段解析excel中文本的代碼進(jìn)行抽離;
// 加載按鈕的回調(diào) async function beforeUpload(file){ // 解析圖片 imageList.value = await getExcelImage(file); // 解析數(shù)據(jù) getExcelData(file); } // 解析數(shù)據(jù) function getExcelData(file) { let fileReader = new FileReader(); // 構(gòu)建fileReader對(duì)象 fileReader.readAsArrayBuffer(file); // 讀取指定文件內(nèi)容 // 讀取操作完成時(shí) fileReader.onload = function (e) { try { let data = e.target.result; // 取得數(shù)據(jù)data // console.log(data); let workbook = XLSX.read(data, { type: "binary" }); // 將data轉(zhuǎn)換成excel工作表數(shù)據(jù) // console.log("Excel工作簿", workbook); const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 獲取第一個(gè)工作表 // console.log("第一張工作表", worksheet); /* * XLSX.utils.sheet_to_json 輸出JSON格式數(shù)據(jù) * 獲取指定工作表中的數(shù)據(jù)sheetlist[],整個(gè)表中的數(shù)據(jù)存放在一個(gè)數(shù)組sheetlist中; * sheetlist數(shù)組中的每個(gè)元素均為一個(gè)數(shù)組rowlist,是每一行的數(shù)據(jù); */ const sheetlist = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); // console.log('sheetlist', sheetlist); } catch (e) { console.log("文件類型不正確"); return; } }; }
4、封裝數(shù)據(jù)
根據(jù)上述內(nèi)容,excel文件中的圖片和文本內(nèi)容均已取得,如何封裝稱自己想要的數(shù)據(jù)格式,可以自行解決了;這里給出我自己在el-table中需要的數(shù)據(jù)格式封裝方法;
(1)封裝思路
獲取到的sheetlist的數(shù)據(jù)格式如下:
sheetlist = [ ["name", "age", "avatar"], ["張三", 18], ["李四", 20], ]
這并不是我們想要的,期望的格式應(yīng)該是如下所示:
最外層是一個(gè)數(shù)組[ ],里面是每個(gè)數(shù)據(jù)對(duì)象itemObj;
[ { name:'張三', age:18, avatar:"imageUrl" }, { name:'李四', age:20, avatar:"imageUrl" }, ]
首先,我們可以看出sheetlist[0],就是我們想要的el-table的列名;其次,使用雙重循環(huán)拆解重組數(shù)據(jù);
創(chuàng)建一個(gè)對(duì)象obj,在我們?nèi)〉絪heetlist[0][0],也就是“name”的時(shí)候,讓obj[“name”] = “張三”,obj[“age”] = “18”,obj[“avatar”] = “”,也就是obj[sheetlist[0][0]] = sheetlist[1][0]、obj[sheetlist[0][1]] = sheetlist[1][1],obj[sheetlist[0][2]] = sheetlist[1][2],以此類推...;
這里,剛剛好在給obj[“avatar”] = “”賦值的時(shí)候我們可以賦值成imagelist中的值,也就是obj[sheetlist[0][2]] = imagelist[i];注意,imagelist中存儲(chǔ)的是base64編碼值,別忘記賦值之前進(jìn)行編碼轉(zhuǎn)換,obj[sheetlist[0][2]] = `data:image/png;base64,${imageList.value[i]};
最后,將新建的obj對(duì)象push進(jìn)el-table綁定的數(shù)據(jù)源中即可看到結(jié)果了;
(2)實(shí)現(xiàn)過(guò)程
我們編寫一個(gè)封裝數(shù)據(jù)的方法,并在解析好excel的文本數(shù)據(jù)后調(diào)用它;
獲取el-table的列名;
// 封裝數(shù)據(jù) function formatDate(sheetlist) { tableColumnLabel.value = sheetlist[0]; // 獲取表格列名 }
此時(shí),頁(yè)面上已經(jīng)有了顯示效果;
使用雙重循環(huán)拆解組合數(shù)據(jù),這里不做過(guò)多解釋,大家可以自己寫個(gè)方法,能夠讓我參考參考,感覺(jué)自己寫的也不怎么好;
// 封裝數(shù)據(jù) function formatDate(sheetlist) { tableColumnLabel.value = sheetlist[0]; // 獲取表格列名 for (let i = 0; i < sheetlist.length - 1; i++) { let obj = {}; for (let j = 0; j < sheetlist[0].length; j++) { // 頭像列,則取解析到的imageList中的相應(yīng)值; // 這里要求我們知道excel中存放圖片的列名,否則會(huì)導(dǎo)致讀取失?。? if (sheetlist[0][j] == "avatar") { obj[sheetlist[0][j]] = `data:image/png;base64,${imageList.value[i]}`; // 注意base64編碼的處理 } else { // 非頭像列,直接取值; obj[sheetlist[0][j]] = sheetlist[i + 1][j] ?? ""; } } console.log(obj); } }
可以在控制臺(tái)查看每個(gè)obj對(duì)象的輸出結(jié)果;
最后,將這個(gè)obj對(duì)象push進(jìn)el-table綁定的數(shù)據(jù)源中;
// 封裝數(shù)據(jù) function formatDate(sheetlist) { tableColumnLabel.value = sheetlist[0]; // 獲取表格列名 for (let i = 0; i < sheetlist.length - 1; i++) { // 這里length-1是因?yàn)槲覀兊膕heetlist[0]為列名,實(shí)際的數(shù)據(jù)要少 1; let obj = {}; for (let j = 0; j < sheetlist[0].length; j++) { // 頭像列,則取解析到的imageList中的相應(yīng)值; // 這里要求我們知道excel中存放圖片的列名,否則會(huì)導(dǎo)致讀取失??; if (sheetlist[0][j] == "avatar") { obj[sheetlist[0][j]] = `data:image/png;base64,${imageList.value[i]}`; // 注意base64編碼的處理 } else { // 非頭像列,直接取值; obj[sheetlist[0][j]] = sheetlist[i + 1][j] ?? ""; } } // console.log(obj); tableData.value.push(obj); // 添加到el-table綁定的數(shù)據(jù)源中 } console.log("tableData.value", tableData.value); }
控制臺(tái)查看打印輸出結(jié)果;
頁(yè)面最終顯示效果;
5、現(xiàn)有問(wèn)題
第一,采取這個(gè)方法的前提是得明確知道excel中存放圖片的列名;
第二,圖片是按照在excel中的順序加載的,存在較多未知的隱患;
第三,謹(jǐn)慎使用!謹(jǐn)慎使用!謹(jǐn)慎使用!
總結(jié)
到此這篇關(guān)于前端解析包含圖片的excel文件完整步驟及代碼示例的文章就介紹到這了,更多相關(guān)前端解析含圖片excel文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解微信小程序之scroll-view的flex布局問(wèn)題
這篇文章主要介紹了詳解微信小程序之scroll-view的flex布局問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01javascript實(shí)現(xiàn)數(shù)字時(shí)鐘效果
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)數(shù)字時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02移動(dòng)端翻頁(yè)插件dropload.js(支持Zepto和jQuery)
這篇文章主要為大家詳細(xì)介紹了移動(dòng)端翻頁(yè)插件dropload.js,支持Zepto和jQuery,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07js使用generator函數(shù)同步執(zhí)行ajax任務(wù)
這篇文章主要為大家詳細(xì)介紹了js使用generator函數(shù)同步執(zhí)行ajax任務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09前端實(shí)現(xiàn)word文檔預(yù)覽和內(nèi)容提取的詳細(xì)過(guò)程
在前端直接讀取并原樣展示W(wǎng)ord文檔是一個(gè)相對(duì)復(fù)雜的任務(wù),因?yàn)閃ord文檔的格式(如.doc或.docx)與Web技術(shù)棧使用的格式(HTML、CSS)不兼容,下面這篇文章主要給大家介紹了關(guān)于前端實(shí)現(xiàn)word文檔預(yù)覽和內(nèi)容提取的詳細(xì)過(guò)程,需要的朋友可以參考下2024-05-05javascript實(shí)現(xiàn)異形滾動(dòng)輪播
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)異形滾動(dòng)輪播,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11