使用用vue封装table组件,功能如下
1、是否显示表格的左右侧边框 border true|false(default);
2、 表格的对齐方式 align left(default) | right |center;
3、鼠标移动到每一行是否高亮 disabledHover true|false(default);
4、是否显示间隔斑马纹 stripe true|false(default);
5、是否显示表格正在加载中 loading true|false(default);
6、是否将表头固定 height 传入值表示将表头固定;
7、每行数据多选功能 checkbox选择功能
使用sass编写css,所以复用代码即npm i sass sass-loader。
<template>
<div class="context" ref="container">
<div
:style="{height:height!=''&& height!=0?`${height}px`:'auto',overflow:'auto'}"
class="container"
>
<table class="table" ref="table">
<thead>
<!-- 几行 几列-->
<tr>
<th width="50">
<input type="checkbox" :checked="checked" @change="checkAll" ref="checkedSt" />
</th>
<th v-for="(item,i) in tableHeader" :key="item.key">{{item.name}}</th>
</tr>
</thead>
<tbody>
<tr v-for="(value,i) in tableData" :key="i">
<td>
<input
type="checkbox"
:checked="checkedBool(value)"
@change="iptChecked(value,$event)"
/>
</td>
<td v-for="(item,i) in tableHeader" :key="i">{{value[item.key]}}</td>
</tr>
</tbody>
</table>
<div class="loading" v-if="loading">
<div v-show="spanShow">
<span class="round"></span>
</div>
</div>
</div>
<!-- <button @click="handler">按钮</button> -->
</div>
</template>
<script>
import { cloneDeep } from "lodash/cloneDeep";
export default {
name: "hlTable",
data() {
return {
checkBox: [],
spanShow: false
};
},
props: {
tableData: {
//表格数据
type: Array,
default: () => []
},
tableHeader: {
//表格头
type: Array,
default: () => [],
require: true
},
border: {
//是否显示表格的左右侧边框
type: Boolean,
default: false
},
align: {
//表格的对齐方式
type: String,
default: "left"
},
disabledHover: {
//鼠标移动到每一行是否高亮
type: Boolean,
default: true
},
stripe: {
//是否显示间隔斑马纹
type: Boolean,
default: false
},
loading: {
//是否显示表格正在加载中
type: Boolean,
default: false
},
checkArr: {
type: Array,
default: () => []
},
height: {
type: String,
default: ""
}
},
beforeMounted() {
//浅拷贝不好
// this.checkBox=[...this.checkArr];
this.checkBox = cloneDeep(this.checkArr);
},
mounted() {
this.init();
},
computed: {
position() {
if (this.align !== "left") {
window.document.body.setAttribute("position", this.align);
}
return;
},
borderl() {
if (this.border) {
window.document.body.setAttribute("border", this.border);
}
return;
},
hover() {
if (this.disabledHover) {
window.document.body.setAttribute("hover", this.disabledHover);
}
return;
},
stripel() {
if (this.stripe) {
window.document.body.setAttribute("stripe", this.stripe);
}
return;
},
//全选框的状态
checked() {
return this.tableData.length === this.checkArr.length;
}
},
watch: {
checkBox() {
if (this.checkBox.length !== this.tableData.length) {
if (this.checkBox.length !== 0) {
return (this.$refs.checkedSt.indeterminate = true);
}
}
this.$refs.checkedSt.indeterminate = false;
},
loading: {
immediate: true,
handler: function() {
console.log(this);
if (this.loading) {
var num = 0;
this.timer = setInterval(() => {
this.spanShow = true;
num++;
if (num === 3) {
if (this.spanShow == true) {
this.spanShow = false;
num = 0;
}
}
console.log(1);
}, 1000);
} else {
console.log(2);
clearInterval(this.timer);
}
}
}
},
methods: {
//初始化表格的样式
init() {
this.position;
this.borderl;
this.hover;
this.stripel;
if (this.height) {
var table = this.$refs.table;
var container = this.$refs.container;
var cloneTable = table.cloneNode();
container.style.paddingTop =
table.children[0].getBoundingClientRect().height + "px";
cloneTable.appendChild(table.children[0]);
container.appendChild(cloneTable);
cloneTable.classList.add("fixPosition");
}
},
//点击每一行的选择框触发的函数。数据是单向数据流,不能直接修改父级的数据。
iptChecked(value, e) {
//如果已经选择的数据里有当前选择的数据则删除,如果没有则添加。
var flag = this.checkBox.some(item => item.id === value.id);
if (!flag) {
this.checkBox.push(value);
} else {
var index = this.checkBox.findIndex(item => item.id === value.id);
this.checkBox.splice(index, 1);
}
this.$emit("update:checkArr", this.checkBox);
},
//点击全选的函数
checkAll() {
if (this.checkBox.length === this.tableData.length) {
this.checkBox = [];
} else {
this.checkBox = this.tableData;
}
this.$emit("update:checkArr", this.checkBox);
},
//每个选择框的状态
checkedBool(value) {
return this.checkBox.some(item => item.id === value.id);
}
// handler() {
// if (!this.isShow) {
// return this.isShow = true;
// } else {
// return this.isShow = false;
// }
// }
}
};
</script>
<style lang="scss" scoped>
body {
text-align: left;
}
$table-boeder-color: #eee; //设置表格的border颜色
$tr-align-left: left; //设置tr的left对齐位置
$tr-align-center: center; //设置tr的center对齐位置
$tr-align-right: right; //设置tr的right对齐位置
//@mixin 后面的函数名称为自定义。
@mixin border($bool) {
[border="true"] & {
border-left: 1px solid $table-boeder-color;
border-right: 1px solid $table-boeder-color;
}
}
//设置tr的hover行为
@mixin hover($color) {
&:hover {
background: $color;
}
[hover="true"] & {
&:hover {
background: aliceblue;
}
}
}
//设置对齐方向
@mixin position($bool) {
text-align: $bool;
[position="right"] & {
text-align: right;
}
[position="center"] & {
text-align: center;
}
}
//设置每行是否间隔行
@mixin stripe($bool) {
background: $bool;
[stripe="true"] & {
&:nth-child(odd) {
background: #5f87e0;
}
}
}
.context {
height: 100%;
position: relative;
.fixPosition {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.loading {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
text-align: center;
background: #fff;
opacity: 0.9;
.round {
display: inline-block;
width: 0px;
height: 0px;
border-radius: 50%;
background: cornflowerblue;
opacity: 1;
left: 50%;
top: 50%;
position: absolute;
transform: translate(-50%, -50%);
animation: change 5s;
-moz-animation: change 5s;
-webkit-animation: change 5s;
-o-animation: change 5s;
@keyframes change {
from {
width: 0px;
height: 0px;
opacity: 1;
}
to {
width: 80px;
height: 80px;
opacity: 0;
}
}
}
}
table {
width: 100%;
border-spacing: 0;
font-size: 14px;
background: #fff;
@include border(false);
thead {
background-color: aliceblue;
}
th,
td {
border-bottom: 1px solid #eee;
padding: 10px;
}
tr {
@include hover("#fff");
@include position(left);
}
tbody {
tr {
@include stripe("#fff");
}
}
}
}
</style>