效果图:
解析表格
解析表格数据安装插件:npm install xlsx --save-dev
安装完成之后,在页面进行导入:import XLSX from 'xlsx'
解析表格用到3个方法
// 点击上传按钮,拿到file对象
handleUpload(file) {
this.readWorkbookFromLocalFile(file, this.outputWorkbook)
return false;
},
// 通过XLSX.read方法,拿到workbook对象,调用回调函数,解析workbook对象
readWorkbookFromLocalFile (file, callback) {
let reader = new FileReader();
reader.onload = function(e) {
let data = e.target.result;
let workbook = XLSX.read(data, {type: 'binary'});
if(callback) callback(workbook);
};
reader.readAsBinaryString(file);
},
// 解析workbook对象,拿到数据,调用XLSX.utils.sheet_to_html方法,可以将sheet对象转换为html字符串
outputWorkbook(workbook) {
let sheetNames = workbook.SheetNames; // 工作表名称集合
sheetNames.forEach(name => {
let worksheet = workbook.Sheets[name]; // 这里我们只读取第一张sheet
let html = XLSX.utils.sheet_to_html(worksheet);
/** 由于XLSX.utils.sheet_to_html返回的结果是:
*<html>
<body>
<header></header>
<table>...</table>
</body>
</html>
*所有需要截取字符串,拿到table标签即可
*/
let sIndex = html.indexOf('<table>')
let eIndex = html.indexOf('</table>')
this.excelContent = html.slice(sIndex, eIndex + 8)
});
},
将截取完的字符串赋值给this.excelContent
,可以将表格渲染到页面上
<div v-html='excelContent' class="table-wrapper" ref="tableWrapper"></div>
表格拖拽
这里使用HTML5拖拽,主要涉及的知识有:拖拽drag与拖放drop
给this.excelContent
赋值之后,需要获取到每一个单元格,为其注册ondragstart[拖拽开始]
、ondrag[拖拽中]
、ondragend[拖拽结束]
,同时还需要在每一个td标签增加属性:draggable="true"
在outputWorkbook
方法后面添加如下语句:
let tableWrapper = this.$refs.tableWrapper
// 保证页面上的table渲染完毕
this.$nextTick(() => {
// 给单元格绑定拖拽事件
this.tdList = tableWrapper.querySelectorAll('td')
this.tdList.forEach(item => {
item.setAttribute('draggable','true');
this.drag(item)
})
})
绑定拖拽事件
drag (source) {
source.ondragstart = this.dragstart
source.ondrag = this.dragging
source.ondragend = this.dragend
},
拖拽元素:dragstart
、dragging
、dragend
方法具体实现
// 拖拽开始
dragstart (event) {
event = event || window.event
const target = event.target
// 设置样式
target.className = 'drop-over-upward'
// 存储当前单元格的ID
event.dataTransfer.setData('id', target.id);
// 给除当前单元格之外的其它单元格注册目标拖拽事件
this.tdList.forEach((item, index) => {
if (item !== target) {
item.ondragenter = this.dragenter
item.ondragover = this.dragover
item.ondragleave = this.dragleave
item.ondrop = this.drop
}
})
},
// 拖拽中
dragging () {},
// 拖拽结束
dragend (event) {
event = event || window.event
const target = event.target
// 清空样式
target.className = ''
// 清空存储的数据
event.dataTransfer.clearData()
// 给除当前单元格之外的其它单元格移除事件
this.tdList.forEach((item, index) => {
if (item !== target) {
item.ondragenter = null
item.ondragover = null
item.ondragleave = null
item.ondrop = null
}
})
},
目标元素:dragenter
、dragover
、dragleave
、drop
方法具体实现
// 拖拽元素进入目标元素
dragenter (event) {
event = event || window.event;
const target = event.target
target.className = 'drop-over-downward'
},
// 拖拽元素在目标元素中移动
dragover (event) {
event = event || window.event;
event.preventDefault()
},
// 拖拽元素离开目标元素
dragleave (event) {
event = event || window.event;
const target = event.target
target.className = ''
},
// 拖拽元素放置在目标元素中
drop (event) {
event = event || window.event;
const target = event.target
target.className = ''
// 列编号
let staticArr = ['A', 'B', 'C']
// td的ID字符串'A1'
let tdIdStr = event.dataTransfer.getData('id').split('-')[1]
// 将ID通过正则拆分成【‘A’, '1', ''】
let arr = tdIdStr.split(/(\d+)/)
// 列字母
let pre = arr[0]
// 列Index
let cIndex = staticArr.findIndex(item => item === pre)
// 行Index
let rIndex = parseInt(arr[1]) - 1
// 通过rIndex、cIndex获取源ID
let source = this.$refs.tableWrapper.querySelector('table').querySelectorAll('tr')[rIndex].querySelectorAll('td')[cIndex]
// 交换内容
let tempInnerHTML = target.innerHTML
target.innerHTML = source.innerHTML
source.innerHTML = tempInnerHTML
}
注意:dragging
和dragover
方法不可以删除