vue的table表格组件的封装
封装的vue表格组件,整理记录下1,分为两个组件去封装,一个是基本的表格的框架组件,一个是行内容组件基本的表格框架组件:增加了移动调整列大小功能<template><div class="data-table"><!-- 表格标题 --><table><thead><tr ref="dataTableHead"><th
·
封装的vue表格组件,整理记录下
1,分为两个组件去封装,一个是基本的表格的框架组件,一个是行内容组件
基本的表格框架组件:
增加了移动调整列大小功能
<template>
<div class="data-table">
<!-- 表格标题 -->
<table>
<thead>
<tr ref="dataTableHead">
<th v-if="isCheck">
<input type="checkbox" class="text-input" v-model="isAll" />
</th>
<th v-if="isNum">{{ $t("common.num") }}</th>
<slot name="data-table-head"></slot>
<th></th>
</tr>
</thead>
</table>
<div class="table-content">
<!-- 表格数据内容 -->
<table v-show="tableData.length > 0 && !isLoading">
<tbody ref="dataTableContent">
<slot name="data-table-content"></slot>
<!-- <data-table-row :idx="idx" :item="item" v-for="(item, idx) in tableData" :key="idx"></data-table-row> -->
</tbody>
</table>
<!-- 暂无数据 -->
<div class="table-nodata" v-show="tableData.length == 0 && !isLoading">{{ $t("common.nodata") }}</div>
<div class="table-loading" v-show="isLoading">{{ $t("common.loading") }}</div>
</div>
</div>
</template>
<script>
export default {
name: "DataTableComp",
props: {
tableData: {
//表格数据
type: Array,
default: () => [],
},
isLoading: {
//是否正在加载数据
type: Boolean,
default: false,
},
isCheck: {
type: Boolean,
default: false,
},
isNum: {
type: Boolean,
default: false,
},
selects: {
type: Array,
default: () => [],
},
},
provide() {
return { dataTable: this };
},
data: () => ({
isAll: false,
selectList: [],
isLoad: false,
}),
watch: {
selectList: {
//多选表格,选中的数据项索引数组
deep: true,
handler() {
if (!this.isLoad) {
this.$emit("update:selects", this.selectList);
this.$emit("table-select", this.selectList);
}
},
},
selects() {
//多选表格,选中的数据项
this.isLoad = true;
this.selectList = this.selects;
var that = this;
this.$nextTick(function() {
that.isLoad = false;
});
},
isAll() {
//是否全选多选表格
if (this.isAll) {
var list = [];
for (var i = 0; i < this.tableData.length; i++) {
list.push(i);
}
this.selectList = list;
} else {
this.selectList = [];
}
},
tableData() {
//表格数据更新,重新渲染
this.isLoad = true;
var that = this;
this.$nextTick(function() {
that.initColumWidth();
that.isLoad = false;
});
},
},
methods: {
clearSelect() {
//多选表格,清空选中
this.isAll = false;
},
listenEvent() {
this.app.$on("table-select-clear", this.clearSelect);
},
offEvent() {
this.app.$off("table-select-clear", this.clearSelect);
},
initColumWidth() {
//初始每列的宽度,保留每次调整后的列宽
if (this.$refs.dataTableContent && this.$refs.dataTableHead) {
if (this.tableData.length > 0 && !this.isLoading) {
var head = this.$refs.dataTableHead;
var body = this.$refs.dataTableContent;
if (body.children) {
for (var i = 0; i < body.children.length; i++) {
for (var j = 0; j < head.children.length - 1; j++) {
var td = body.children[i].children[j];
td.style.width = head.children[j].style.width;
}
}
}
}
}
},
//移动调整列大小
onTableColum() {
var movepage = document.getElementById("moving_page");
if (this.$refs.dataTableContent && this.$refs.dataTableHead) {
var dataTableContent = this.$refs.dataTableContent;
this.$refs.dataTableHead.onmousedown = function(e) {
if (e.target.tagName == "TH" && e.target != this.lastElementChild) {
var elmt = e.target;
var startX = e.pageX;
var distance = e.pageX - elmt.offsetLeft;
var leftRight = distance < elmt.offsetWidth * 0.5 ? "left" : "right";
var elmt1 = leftRight == "left" ? elmt.previousElementSibling : elmt.nextElementSibling;
if (elmt1 != this.lastElementChild) {
var width = elmt.offsetWidth;
var width1 = elmt1.offsetWidth;
movepage.style.display = "flex";
movepage.style.cursor = "ew-resize";
movepage.onmousemove = function(e) {
var w = e.pageX - startX + width;
var w1 = width + width1 - w;
elmt.style.width = w + "px";
elmt1.style.width = w1 + "px";
for (var i = 0; i < dataTableContent.children.length; i++) {
var td = dataTableContent.children[i].children[elmt.cellIndex];
var td1 = leftRight == "left" ? td.previousElementSibling : td.nextElementSibling;
td.style.width = w + "px";
td1.style.width = w1 + "px";
}
};
movepage.onmouseup = function() {
movepage.onmousemove = null;
movepage.style.display = "none";
};
}
}
e.preventDefault();
};
}
},
},
mounted() {
this.listenEvent();
this.onTableColum();
},
beforeDestroy() {
this.offEvent();
},
};
</script>
<style lang='scss'>
.data-table {
display: block;
overflow-x: hidden;
overflow-y: hidden;
padding-bottom: 0.1rem;
height: 100%;
width: 100%;
table {
background: white;
width: 100%;
border-collapse: collapse;
border-spacing: 0;
thead > tr {
background: #cedeee;
border-radius: 0.4rem;
line-height: 3rem;
white-space: nowrap;
height: 3rem;
display: flex;
flex-direction: row;
cursor: ew-resize;
}
thead > tr > th {
text-align: center;
font-size: 1.4rem;
font-weight: normal;
}
thead > tr > th:not(:last-child) {
// border-right: solid 1px #0095ec;
min-width: 5rem;
}
thead > tr > th:last-child {
width: 0.8rem;
}
tbody > tr {
display: flex;
flex-direction: row;
border-radius: 0.4rem;
align-items: center;
line-height: 1.6rem;
min-height: 3rem;
}
tbody > tr:nth-child(even) {
background: #f3f3f3;
}
tbody > tr:hover,
tbody > tr.active {
color: #388dea;
background-color: #d9edf6;
}
tbody > tr.active {
font-weight: bold;
}
tbody > tr > td {
text-align: center;
font-size: 1.2rem;
min-width: 4rem;
word-break: break-word;
white-space: normal;
> span {
max-width: 100%;
white-space: normal;
word-break: break-word;
}
a {
color: #0095ec;
text-decoration: underline;
font-size: 1.2rem;
cursor: pointer;
}
button:nth-child(odd),
button.btn-white {
@extend .btn-white;
height: 2.4rem !important;
line-height: 2.4rem !important;
}
button:nth-child(even),
button.btn-orange {
@extend .btn-orange;
height: 2.4rem !important;
line-height: 2.4rem !important;
}
a:not(:last-child),
button:not(:last-child) {
margin-right: 0.8rem;
}
}
}
.table-content {
height: calc(100% - 3.1rem);
overflow-y: auto;
overflow-x: hidden;
border: dashed 0.1rem gainsboro;
border-top: none;
.table-nodata {
font-weight: bold;
margin: 0.8rem;
font-size: 1.2rem;
border: #e2a814 0.1rem dashed;
background-color: #f6f0ca;
display: flex;
align-items: center;
justify-content: center;
height: calc(100% - 1.8rem);
color: black;
}
.table-loading {
@extend .table-nodata;
color: red;
font-size: 1.4rem;
}
}
}
</style>
行内容组件:
<template>
<tr>
<td v-if="dataTable.isCheck">
<input type="checkbox" class="text-input" v-model="dataTable.selectList" :value="idx" />
</td>
<td v-if="dataTable.isNum">{{idx+1}}</td>
<slot />
</tr>
</template>
<script>
export default {
name: "DataTableRow",
props: {
idx: {
type: Number,
default: 0
},
item: {
type: Object,
default: () => { }
}
},
inject: ["dataTable"],
provide () {
return { dataTableRow: this };
}
};
</script>
<style>
</style>
2,main.js中全局定义使用:
import DataTableComp from "@/components/comp/table/DataTableComp";
import DataTableRow from "@/components/comp/table/DataTableRow";
Vue.use({
install: function() {
Vue.component("data-table", DataTableComp); //数据表格组件
Vue.component("data-table-row", DataTableRow); //数据表格行组件
},
});
3,在组件中使用
<data-table :is-num="false" :table-data="dataList" :is-check="true" :is-custom="true" :selects.sync="selectList">
<template slot="data-table-head">
<th style="width:15rem">{{ $t("common.name") }}</th>
<th style="width:12rem">{{ $t("common.age") }}</th>
<th style="width:12rem">{{ $t("common.company") }}</th>
</template>
<template slot="data-table-content">
<data-table-row v-for="(item, idx) in dataList" :key="'abc' + idx" :idx="idx" :item="item">
<td style="width:15rem">{{ item.name}}</td>
<td style="width:12rem">{{ item.age}}</td>
<td style="width:12rem">{{ item.company}}</td>
</data-table-row>
</template>
</data-table>
is-num是否显示行的序号,is-check是否可以选中,select.sync是选中的行数的序号
更多推荐
已为社区贡献5条内容
所有评论(0)