<el-table
ref="xxTable"
:data="viewZoneData"
>
<el-table-column type="index" label="序号" width="50" align="center" />
</el-table-column>
</el-table>
<div v-if="showLoad" class="load-box"><i class="el-icon-loading" /> 加载中</div>
<script>
import { debounce } from '@/common/debounce'
data() {
return {
tableList: [], // 接口拿带大量数据后传递给这个变量!!!
originData: [],
viewZoneData: [],
isNeedLoad: false, // 是否需要进行加载操作
cutIndex: 0,
showLoad: false
}
},
mounted() {
window.addEventListener('scroll', this.loadData, true)
},
beforeDestroy() {
window.removeEventListener('scroll', this.loadData, true)
},
watch: {
tableList(val) {
this.originData = common.deepCopy(val)
if (this.originData.length >= 20) {
this.isNeedLoad= true
this.viewZoneData= this.originData.slice(0, 20)
this.cutIndex = 20
} else {
this.isNeedLoad= false
this.viewZoneData= this.originData
}
}
},
methods: {
// 加载数据
loadData: debounce(function() {
if (this.isNeedLoad) { // 需要分段加载才触发以下代码
const offsetHeight = this.$refs.xxTable.$el.offsetHeight
const scrollTop = this.$refs.xxTable.bodyWrapper.scrollTop // 一直都是0
const scrollHeight = this.$refs.xxTable.bodyWrapper.scrollHeight
let loadMore = offsetHeight + scrollTop + 50 >= scrollHeight
if (loadMore) {
loadMore = false
this.showLoad = true
const newData = this.originData.slice(this.cutIndex, this.cutIndex += 20)
this.viewZoneData.splice(this.cutIndex, 0, ...newData)
this.$nextTick(() => {
this.showLoad = false
})
}
}
}, 150, false), //当滚动条触底时,150ms后加载下一分段数据,可根据需求调整速率
httpRequest: function(item) {
this.name = item.file.name
const file = item.file
const fd = new FormData()
fd.append('file', file)
API.deliverImportAPI(fd).then(res => {
if (res.data.flag === 'success') {
const importData = res.data.data // 导入的数据
this.tableList = []
this.tableList = importData
this.$successMsg('导入文件完成')
} else {
this.$errorMsg(res)
}
}).catch(() => {
})
},
}
debounce.js
/**
* 防抖函数
* @param func 用户传入的防抖函数
* @param wait 等待的时间
* @param immediate 是否立即执行
*/
export const debounce = function(func, wait = 50, immediate = false) {
// 缓存一个定时器id
let timer = null
let result
const debounced = function(...args) {
// 如果已经设定过定时器了就清空上一次的定时器
if (timer) {
clearTimeout(timer)
}
if (immediate) {
const callNow = !timer
// 等待wait的时间间隔后,timer为null的时候,函数才可以继续执行
timer = setTimeout(() => {
timer = null
}, wait)
// 未执行过,执行
if (callNow) result = func.apply(this, args)
} else {
// 开始一个定时器,延迟执行用户传入的方法
timer = setTimeout(() => {
// 将实际的this和参数传入用户实际调用的函数
func.apply(this, args)
}, wait)
}
return result
}
debounced.cancel = function() {
clearTimeout(timer)
timer = null
}
// 这里返回的函数时每次用户实际调用的防抖函数
return debounced
}
common.js
/*
* @Author: xxx
* @Descripttion: 深拷贝
* @Date: 2021.xx.xx
*/
function typeOf(obj) {
const toString = Object.prototype.toString
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
}
return map[toString.call(obj)]
}
function deepCopy(data) {
const t = typeOf(data)
let o
if (t === 'array') {
o = []
} else if (t === 'object') {
o = {}
} else {
return data
}
if (t === 'array') {
for (let i = 0; i < data.length; i++) {
o.push(deepCopy(data[i]))
}
} else if (t === 'object') {
for (const i in data) {
o[i] = deepCopy(data[i])
}
}
return o
}
export default {
deepCopy
}