自己封装的移动端可横向滚动表格组件,可实现滚动加载
<template>
<div ref="table">
<div :style="tableStyle" v-scrollX="this">
<div>
<div class="thead">
<div
v-for="(item, index) in columns"
:key="item + index"
class="thead-item"
>
<div
:style="{
left: left + 'px',
background: '#ccc'
}"
>
<div>{{ item.lable }}</div>
</div>
</div>
</div>
</div>
<div class="tbody" :style="tbodyStyle" v-if="dataList.length >= 0">
<div
v-for="(item, index) in dataList"
:key="item + index"
class="tbody-item"
>
<div
v-for="(items, indexs) in columns"
:key="items + indexs"
:style="styleObject(items, 1)"
@click="lineClick(indexs, index)"
>
<div
:style="{
...styleObject(items, 2),
left: left + 'px'
}"
>
<div
v-if="!items.render"
style="white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;"
>
{{ item[items.key] }}
</div>
<!-- <render-template
v-if="items.render"
:render="items.render"
:row="item"
:index="index"
:column="items"
></render-template> -->
</div>
</div>
</div>
<div v-if="downLoad" class="downLoad">{{ down_load_text }}</div>
<!--infinite-loading这个组件要放在列表的底部,滚动的盒子里面-->
<infinite-loading
spinner="spiral"
:on-infinite="infiniteHandler"
:distance="200"
class="infinite-loading-wrap"
ref="infiniteLoading"
>
<div
slot="spinner"
style="text-align:left;margin-left:12%;margin-bottom:10px"
>
加载中...
</div>
<div
slot="no-more"
style="text-align:left;margin-left:12%;margin-bottom:10px"
>
无更多数据!
</div>
<div
slot="no-results"
style="text-align:left;margin-left:40%;margin-bottom:10px"
>
无数据
</div>
<div slot="error" slot-scope="{ trigger }">
Error Data, click
<a href="javascript:;" @click="trigger">here</a> toretry
</div>
</infinite-loading>
<div
v-if="dataList.length < 1"
class="tbody noData"
:style="noDataStyle"
>
<span style="display: block;width:100%;margin-right:25rem"></span>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from "vue";
import InfiniteLoading from "vue-infinite-loading";
import { Toast } from "mint-ui";
Vue.component("render-template", {
name: "renderTemplate",
functional: true,
props: {
render: {
type: Function
},
row: {
type: Object
},
index: {
type: [String, Number]
},
column: {
type: Object
}
},
render: (h, ctx) => {
const params = {
row: ctx.props.row,
index: ctx.props.index
};
if (ctx.props.column) params.column = ctx.props.column;
return ctx.props.render(h, params);
}
});
export default {
data() {
return {
left: "0",
lastScrollTop: "0",
downLoad: false,
down_load_text: "加载中...",
page: 1
};
},
components: {
InfiniteLoading
},
props: {
selectedValue: {
type: String,
default: ""
},
findInput: {
type: String,
default: ""
},
width: {
//table的宽度
type: [String, Number],
default: "100%"
},
height: {
//table的高度
type: [String, Number],
default: 490
},
border: {
//是否显示下边框
type: Boolean,
default: false
},
columns: Array,
dataList: Array,
noDataText: {
type: String,
default: "暂无数据"
},
offset: {
type: [String, Number],
default: "0"
}
},
computed: {
tableStyle() {
const { width, height, dataList, downLoad } = this;
let style = {
overflowX: "scroll",
overflowY: "hidden",
position: "relative"
};
if (isNaN(Number(width))) {
style.width = width;
} else {
style.width = width + "px";
}
if (isNaN(Number(height))) {
style.height = `calc(${height} + 36px)`;
} else {
style.height = Number(height) + 36 + "px";
}
if (dataList.length < 1 || downLoad) style.overflowX = "hidden";
return style;
},
tbodyStyle() {
const { height } = this;
let style = {};
if (isNaN(Number(height))) {
style.height = height;
} else {
style.height = height + "px";
}
return style;
},
noDataStyle() {
const { height } = this;
let style = { height: "100px", lineHeight: "100px" };
if (!isNaN(Number(height))) {
style.height = height + "px";
style.lineHeight = height + "px";
}
return style;
}
},
created() {},
mounted() {
// Toast("Upload Complete");
},
methods: {
resetLoad() {
this.getDataList(this.page);
},
relResetLoad() {
this.dataList.splice(0); //置空数组
this.page = 1;
this.$refs.infiniteLoading.$emit("$InfiniteLoading:reset");
},
lineClick(Columnindex, lineIndex) {
console.log(Columnindex);
// index = 0 为第一列点击 index = 1 为第二列点击
if (Columnindex == 0) {
this.$router.push({
path: "/aq/orderAdd",
query: { lineData: this.dataList[lineIndex], operate: "编辑" }
});
} else if (Columnindex == 1) {
//执行删除逻辑 http://192.168.194.24:8082/form/formDefData/removeData/ss_order/0d1afb926fcb06be7dafc80ca1f49c6e
let url =
Vue.__ctx +
"/form/formDefData/removeData/ss_order/" +
`${this.dataList[lineIndex].id}`;
var get = Vue.baseService.get(url);
get.then(data => {
Toast(data.msg);
this.dataList.splice(0); //置空数组
this.page = 1;
this.getDataList(this.page);
});
}
},
infiniteHandler() {
setTimeout(() => {
this.page++;
this.getDataList(this.page);
}, 600);
},
async getDataList(page) {
const list = await this.common.getDataList(
page,
5,
this.selectedValue,
this.findInput
);
if (list.length == 0) {
this.$refs.infiniteLoading.$emit("$InfiniteLoading:complete");
} else {
this.dataList.push(...list);
this.dataList.forEach(item => {
item.edit = "修改";
item.del = "删除";
});
this.$refs.infiniteLoading.$emit("$InfiniteLoading:loaded");
}
},
styleObject(item = {}, type = 1) {
let style = {};
if (type == 2) {
style = {
textAlign: "center"
};
if (Boolean(item.align)) style.textAlign = item.align;
if (Boolean(item.fixed)) {
style.position = "absolute";
style.zIndex = "10";
}
}
if (Boolean(item.width) && isNaN(Number(item.width)))
style.width = item.width;
if (Boolean(item.width) && !isNaN(Number(item.width)))
style.width = (type == 1 ? Number(item.width) + 20 : item.width) + "px";
return style;
}
},
watch: {
dataList: {
handler(value) {
console.log(value);
this.down_load_text = "加载完成";
setTimeout(() => {
this.downLoad = false;
this.down_load_text = "加载中...";
}, 2000);
},
deep: true
}
},
directives: {
scrollX: {
inserted: function(el, binding, vnode) {
el.addEventListener("scroll", function(e) {
const that = vnode.context;
that.left = e.srcElement.scrollLeft;
});
}
}
}
};
</script>
<style scoped>
.thead {
display: flex;
width: auto;
border: 1px solid black;
border-bottom: none;
border-top: none;
}
.thead > div {
background: white;
position: relative;
border-right: 1px solid black;
border-top: 1px solid black;
font-weight: 555;
text-align: center;
}
.thead .thead-item > div {
width: 110px;
}
.thead .thead-item:nth-child(1) > div {
width: 60px;
}
.thead .thead-item:nth-child(2) > div {
width: 60px;
}
.tbody {
width: fit-content;
overflow-x: hidden;
overflow-y: scroll;
position: relative;
background: white;
border-right: none;
}
.tbody .tbody-item {
display: flex;
width: max-content;
}
.tbody .tbody-item > div {
position: relative;
background: white;
border-bottom: 1px solid black;
border-left: 1px solid black;
padding: 5px;
height: 30px;
width: 100px;
}
.tbody .tbody-item > div:nth-child(1) {
width: 50px;
}
.tbody .tbody-item > div:nth-child(1) > div {
display: block;
width: 45px;
height: 25px;
background-color: #409eff !important;
border-radius: 5px;
color: white;
font-size: 14px;
}
.tbody .tbody-item > div:nth-child(2) {
width: 50px;
}
.tbody .tbody-item > div:nth-child(2) > div {
display: block;
width: 45px;
height: 25px;
background-color: #409eff !important;
border-radius: 5px;
color: white;
font-size: 14px;
}
.tbody .tbody-item > div:last-child {
border-right: 1px solid black;
}
.noData {
width: 100%;
background: white;
text-align: center;
}
.downLoad {
width: 100%;
line-height: 36px;
background: #f7f8fa;
text-align: center;
}
</style>
在需要引用的界面 import Table from "@/utils/table.vue";
<Table
:dataList="dataList"
:columns="columns"
ref="table"
>
</Table>
dataList为表格数据
columns为表格列例:
columns: [
{ lable: "修改", key: "edit" },
{ lable: "删除", key: "del" },
{
lable: "订货单号",
key: "order_code"
},
{
lable: "订货重量",
key: "order_weight"
},
{
lable: "产品类型",
key: "product_type"
},
{
lable: "存货编码",
key: "invcode"
},
{
lable: "存货名称",
key: "invname"
},
{
lable: "规格",
key: "invspec"
},
{
lable: "型号",
key: "invtype"
},
{
lable: "订货日期",
key: "order_date"
},
{
lable: "创建人",
key: "create_by"
},
{
lable: "创建日期",
key: "create_date"
}
],

