一个简单的例子来理解:
读取用户上传的 Excel 文件(.xlsx),解析内容,并以表格形式在页面上显示出来。
它依赖一个外部库:XLSX.js(即 SheetJS),用于解析 Excel 数据。
代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>上传Excel文件</h2>
<input type="file" name="" id="excelFile" accept=".xlsx, .xls">
<div id="output"></div>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js
// 读取excel并提取列内容
const UploadFie = document.querySelector("#excelFile")
UploadFie.addEventListener("change", handleFile)
function handleFile(event) {
const file = event.target.files[0]
// console.log(event.target.files[0])
//
const reader = new FileReader()
reader.onload = function(e) {
const data = new Uint8Array(e.target.result)
const workbook = XLSX.read(data, {type: "array"})
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
// 转为 json 格式
const jsonData = XLSX.utils.sheet_to_json(worksheet)
// 渲染结果
renderTable(jsonData)
}
//
reader.readAsArrayBuffer(file)
}
function renderTable(data) {
const output = document.querySelector("#output")
output.innerHTML = ""
if (data.length === 0) {
output.textContent = "没有数据"
return
}
const table = document.createElement("table")
table.style.border = "1"
const thead = table.insertRow()
Object.keys(data[0]).forEach(key => {
const th = document.createElement("th")
th.textContent = key
thead.appendChild(th)
})
data.forEach(row => {
const tr = table.insertRow()
Object.values(row).forEach(value => {
const td = tr.insertCell()
td.textContent = value
})
})
output.appendChild(table)
}
带注释js代码
// 获取页面上 ID 为 "excelFile" 的 <input type="file"> 元素,用于文件上传
const UploadFie = document.querySelector("#excelFile");
// 给文件上传输入框添加事件监听器,监听 "change" 事件(用户选中文件时触发)
UploadFie.addEventListener("change", handleFile);
// 文件选择后的处理函数
function handleFile(event) {
// 获取用户选择的第一个文件对象(如果选择多个,只取第一个)
const file = event.target.files[0];
// 创建一个 FileReader 实例,用于读取文件内容
const reader = new FileReader();
// 当文件读取完成后触发 onload 回调函数
reader.onload = function(e) {
// 将读取到的 ArrayBuffer 包装成 Uint8Array 类型的字节数组
const data = new Uint8Array(e.target.result);
// 使用 SheetJS (XLSX) 读取 Excel 文件内容,指定类型为 "array"
const workbook = XLSX.read(data, { type: "array" });
// 获取 Excel 的第一个工作表名称
const firstSheetName = workbook.SheetNames[0];
// 获取第一个工作表对象
const worksheet = workbook.Sheets[firstSheetName];
// 将工作表数据转换为 JSON 格式数组,每一行为一个对象
const jsonData = XLSX.utils.sheet_to_json(worksheet);
// 将数据渲染为 HTML 表格并显示在页面上
renderTable(jsonData);
};
// 将文件内容以 ArrayBuffer(二进制缓冲区)方式读取(适用于 Excel)
reader.readAsArrayBuffer(file);
}
// 渲染 JSON 数据为 HTML 表格,并插入到页面中
function renderTable(data) {
// 获取用于显示表格的容器(一般是一个 <div id="output">)
const output = document.querySelector("#output");
// 清空上一次渲染的内容
output.innerHTML = "";
// 如果数据为空,显示提示文字并结束函数
if (data.length === 0) {
output.textContent = "没有数据";
return;
}
// 创建一个新的 HTML 表格元素
const table = document.createElement("table");
table.style.border = "1"; // 设置表格边框(简易做法)
// 创建表头(thead),使用数据的键(字段名)作为列名
const thead = table.insertRow(); // 插入第一行作为表头
Object.keys(data[0]).forEach(key => {
const th = document.createElement("th"); // 创建表头单元格
th.textContent = key; // 设置列名(字段名)
thead.appendChild(th); // 将表头单元格添加到表头行中
});
// 遍历数据数组,为每一行数据创建表格行
data.forEach(row => {
const tr = table.insertRow(); // 创建新行
Object.values(row).forEach(value => {
const td = tr.insertCell(); // 创建单元格
td.textContent = value; // 填入单元格的值
});
});
// 将完整表格添加到页面上的容器中
output.appendChild(table);
}
结构总览 & 难理解的点
代码分为三大部分:
- 监听文件上传:
UploadFie.addEventListener(...)
- 处理上传的文件内容并解析 Excel:
handleFile
函数 - 将数据渲染成 HTML 表格:
renderTable
函数
const data = new Uint8Array(e.target.result);
解释:
上面代码中:reader.readAsArrayBuffer(file);
我们通过 FileReader
的 readAsArrayBuffer()
方法来读取文件内容,读取完成后触发 reader.onload
,其事件对象 e
中包含的 e.target.result
是一个 ArrayBuffer
。
ArrayBuffer
是一种原始的、通用的二进制数据容器,不能直接读取内容,需要借助视图(如 Uint8Array, DataView, Float32Array 等)
进行解析。
Uint8Array()
Uint8Array
是 JavaScript 中的一种类型化数组(TypedArray)
。- 它提供了对
ArrayBuffer
的结构化、字节级别的访问
const workbook = XLSX.read(data, { type: "array" });
XLSX.read()
要求的是字节数组
SheetJS
的XLSX.read()
方法如果传入{type: "array"}
,它期望的输入是一个Uint8Array
,因此我们必须将原始的ArrayBuffer
包装为Uint8Array
,否则XLSX.read()
无法解析
🔬 ArrayBuffer VS Uint8Array
ArrayBuffer
就像一块原始磁盘空间,你知道有数据,但无法读取。Uint8Array
就像一个读卡器,它能以 8 位为单位读出这些数据。