vue实现滚动加载的表格
脚本之家 / 编程助手:解决程序员“几乎”所有问题!
脚本之家官方知识库 → 点击立即使用
实现效果
滚动加载知识储备
参考ant-design-vue中list滚动加载的思路,使用vue-infinite-scroll加上vue-virtual-scroller作为解决方案。
组件封装
因为整个系统使用的框架是ant-dsign-vue,所以组件封装的变量命名风格尽可能的与a-table保持一致。
1. 组件命名
XScrollTable.vue
2. 提供的props
必填字段:
dataSource -- 数据源
columns -- 表格展示的列信息,插槽用法和a-table不完全一样,下面会提到。
itemSize -- 每行数据的高度
选填字段:
rowKey -- 数据主键标识,默认为'key'
height -- 表格展示区域的高度,默认为500
pageSize -- 表格滚动每次滚动加载的数据量,默认为30
infiniteScrollDistance -- 表格触发加载的距离条件,默认为10
rowSelection -- 表格多选配置,已处理的属性有selectedRowKeys、onChange、width。默认为null,不展示多选。
3.使用举例
首先初始化10000条数据,放在表格中进行显示。
1 2 3 4 5 6 7 8 9 10 | let data = new Array(10000).fill(1); data = data.map((item1, index) => { let item = {}; item.id = index; item.age = "姓名" ; item.address = "地址" ; return item; }); export default data; |
注意:这里之所以加了fill(1),是因为通过Array构造函数产生的数据全是empty,没有数组索引,无法进行map循环。
加载表格
1 2 3 4 5 6 7 8 9 10 11 | < x-scroll-table style = "margin-top: 10px" row-key = "id" :itemSize = "22" :rowSelection = "{selectedRowKeys: selectedRowKeys, onChange: onSelectChange,width:50}" :columns = "columns" :dataSource = "data" > < template slot = "action" slot-scope = "{record,text}" > < a @ click = "handleDetail(record)" >详情</ a > </ template > </ x-scroll-table > |
组件封装总结
1.尽可能地使用computed计算属性
虽然只是简单地封装了表格,但还是需要定义了很多的属性,使用计算属性代替在data里定义变量,可以减少变量的维护工作量。
整个组件只定义了一个page变量,其它都是使用计算属性的方式。
举个栗子:
通过page属性定义一个计算属性来表示当前已经加载的数据量
1 2 3 4 | // 展示的最大下标数量,存在比总数据条数多的情况,使用slice解决这个问题 lastIndex() { return this .pageSize * this .page; }, |
通过这个计算属性同时衍生出其他的计算属性
1 2 3 4 5 6 7 8 | // 表示表格数据是否已经加载完毕 busy() { return this .lastIndex >= this .dataSource.length; }, // 当前已经加载到RecycleScroller滚动组件的数据 tableData() { return this .dataSource.slice(0, this .lastIndex); }, |
通过一个page属性衍生出一系列的计算属性,我只需要维护page属性,其他都是自动计算的。
2.给表格提供插槽
首先通过表格传入的columns参数,计算出需要渲染的列,这里同样使用计算属性。
1 2 3 4 5 6 7 8 9 10 11 12 | // 将列数组转为列对象,将columnFieldKey值作为键,数组项作为值 columnMap() { return this .columns.reduce((returnValue, cur) => { returnValue[cur[columnFieldKey]] = cur; return returnValue; }, {}); }, // 取数组里的列键值--columnFieldKey columnKeys() { return this .columns .map(item => item[columnFieldKey]); }, |
在template中遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div v- for = "(key) of columnKeys" class= "ellipsis-cell" :key= "key" :style= "itemStyle(columnMap[key])" > <slot v- if = "izSlotRender(columnMap[key])" :name= "columnMap[key].scopedSlots.customRender" :record= "row" :text= "row[key]" > </slot> <span v- else :title= "row[key]" >{{ renderItem(row, index, key) }}</span> </div> // 是否使用插槽渲染 izSlotRender(item) { return item.scopedSlots && item.scopedSlots.customRender; }, |
如果在定义columns时传入了scopedSlots和customRender,将使用插槽渲染。
但是这里存在和ant-design-vue中表格插槽渲染不一样的地方。
我通过slot标签定义的插槽,在父组件获取插槽参数的时候,只能使用slot-scope="{record,text}"对象解构的方式。而ant-design-vue表格是可以直接使用slot-scope="record,text"获取参数的。
另一种滚动加载数据的实现
table数据多的时候打开页面会加载一会才显示数据,这样体验不好,所以要做滚动加载数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | < el-table :data = "materielList" style = "width: 100%" class = "familyDataDetail" height = "250" > < el-table-column prop = "eventId" label = "事件ID" > < template scope = "scope" > < label >{{eventMap[scope.row.eventId] == null ? '--': eventMap[scope.row.eventId].sn}}</ label > </ template > </ el-table-column > < el-table-column prop = "title" label = "对应事件" > < template scope = "scope" > < label >{{eventMap[scope.row.eventId] == null ? '--': eventMap[scope.row.eventId].title}}</ label > </ template > </ el-table-column > < el-table-column prop = "age" label = "负责人" > < template scope = "scope" > < label >{{eventMap == null || eventMap[scope.row.eventId] == null || eventMap[scope.row.eventId].personalInformation == null ? '--': eventMap[scope.row.eventId].personalInformation.name}}</ label > </ template > </ el-table-column > < el-table-column prop = "birthday" label = "物料名称" > < template scope = "scope" > < label >{{materirlName}}</ label > </ template > </ el-table-column > < el-table-column prop = "idcardNo" label = "状态" > < template scope = "scope" > < label >{{formatType(scope.row.type)}}</ label > </ template > </ el-table-column > < el-table-column prop = "relationship" label = "数量" > < template scope = "scope" > < label >{{formatUseNum(scope.row.useNum)}}</ label > </ template > </ el-table-column > < el-table-column prop = "ethtic" label = "使用时间" > < template scope = "scope" > < label >{{changeTime(scope.row.createOn)}}</ label > </ template > </ el-table-column > </ el-table > |
下面是js部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | methods: { init (param) { let id = param.param && param.param.id if (id){ this .start = 0 MaterialRecordService.query({param: {baseId: this .baseId, materialId: id},start: this .start,limit: 30}).then(rsp => { //初次请求数据,30条 this .start += 30 this .materielList = rsp.data MissionEventService.microList({ids: rsp.data.map(n => n.eventId)}).then(rsp3 => { this .eventMap = {} rsp3.data.forEach(n => ( this .eventMap[n.id] = n)) }) }) } }, onScroll() { let inner = document.querySelector( '.el-table__body-wrapper' ); if (inner.scrollHeight - inner.scrollTop <= inner.clientHeight){ //为true时证明已经到底,可以请求接口 if ( this .flag){ //设一个滚动事件的开关,(在data里面声明 flag: true)默认为true this .flag = false MaterialRecordService.query({param: {baseId: this .baseId, materialId: this .entity.id},start: this .start,limit:30}).then(rsp => { //每次加载30条 this .materielList = this .materielList.concat(rsp.data) this .start += 30 this .flag = true MissionEventService.microList({ids: rsp.data.map(n => n.eventId)}).then(rsp3 => { rsp3.data.forEach(n => ( this .eventMap[n.id] = n)) }) }) } } } }, mounted () { this .init({... this .param})<br> //监听表格dom对象的滚动事件 document.querySelector( '.el-table__body-wrapper' ).addEventListener( 'scroll' , this .onScroll); } |
在这里我要说明一下监听的dom对象是哪一个
我还要解释下scrollHeight、scrollTop、clientHeight这三个属性
这是我截的别人的图加了几笔
scrollHeight:网页正文全文高度,
scrollTop:网页滚动的高度,
clientHeight:网页可视区域的高度
以上就是vue实现滚动加载的表格的详细内容,更多关于vue 滚动加载的表格的资料请关注脚本之家其它相关文章!
微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
最新评论