1、背景:移动端封装table组件,组件分为三部分:tableHeader、tableBody、index具体效果图如下:
2、tableHeader.vue页面代码:
<template>
<thead>
<tr>
<th
v-for="item in columns"
:width="item.width"
:align="item.align || 'left'"
:key="item.prop"
:style="{
'min-width': `${item['min-width']}`,
'max-width': `${item['max-width']}`
}"
v-html="item.label"
></th>
</tr>
</thead>
</template>
<script>
export default {
name: 'tableHeader',
props: {
columns: {
type: Array,
default: () => []
}
},
methods: {
renderToHtml(col) {
if (typeof col.render === 'function') {
this.$slots[col.prop] = [col.render(row)];
return;
}
return;
}
}
};
</script>
<style scoped>
th {
font-weight: bold;
padding: 0.09rem 0.02rem;
background: #f7f9f9;
color: #8695a1;
word-wrap: break-word;
word-break: break-all;
}
</style>
3、tableBody页面代码:
<template>
<tbody>
<tr
v-for="(item, index) in data"
:key="index"
:class="[stripe && 'stripe', rowClassName]"
>
<td
v-for="(cItem, cIndex) in columns"
:width="cItem.width"
:align="cItem.align"
:key="cIndex"
:style="{
'min-width': cItem['min-width'],
'max-width': cItem['max-width']
}"
>{{ item[cItem.prop] }}</td
>
</tr>
</tbody>
</template>
<script>
export default {
name: 'tableBody',
props: {
columns: {
type: Array,
default: () => []
},
data: {
type: Array,
default: () => []
},
stripe: {
type: Boolean,
default: false
},
rowClassName: {
type: String,
default: ''
}
}
};
</script>
<style scoped>
.stripe:nth-child(even) {
background-color: #f8faff;
}
td {
padding: 0.13rem 0.02rem;
border-bottom: 0.01rem solid #e8edf0;
color: #253440;
word-wrap: break-word;
word-break: break-all;
}
</style>
4、index.vue页面代码
<template>
<div class="table">
<table>
<table-header
v-if="showHeader"
ref="tableHeader"
:columns="columns"
></table-header>
<table-body
v-if="data.length > 0"
ref="bodyWrapper"
:stripe="stripe"
:row-class-name="rowClassName"
:row-style="rowStyle"
:style="{
width: bodyWidth
}"
:columns="columns"
:data="data"
>
</table-body>
</table>
<p v-if="data.length == 0" class="empty-data">暂无数据</p>
</div>
</template>
<script>
import TableHeader from './tableHeader.vue';
import TableBody from './tableBody.vue';
export default {
name: 'yssTable',
components: {
TableHeader,
TableBody
},
props: {
showHeader: {
type: Boolean,
default: true
},
columns: {
type: Array,
default: () => []
},
data: {
type: Array,
default: () => []
},
stripe: {
type: Boolean,
default: false
},
rowClassName: {
type: String,
default: ''
},
rowStyle: {
type: Object,
default: () => {}
},
bodyWidth: {
type: Number,
default: null
},
emptyBlockStyle: {
type: Object,
default: () => {}
},
emptyText: {
type: String,
default: ''
}
}
};
</script>
<style scoped>
table {
width: 100%;
border-collapse: collapse;
font-size: 0.14rem;
}
.empty-data {
text-align: center;
font-size: 14px;
color: #666;
margin-top: 15px;
}
</style>
5、使用
<template>
<div class="table-demo">
<table-demo :columns="columns" :data="tableData"></table-demo>
</div>
</template>
<script>
import TableDemo from './tableDemo';
export default {
name: 'tableDemo',
components: {
TableDemo
},
data() {
return {
columns: [
{
prop: 'name',
label: '姓名',
width: '30%',
'min-width': '0.6rem'
},
{
prop: 'age',
label: '年龄',
align: 'right',
width: '20%',
'min-width': '0.6rem'
},
{
prop: 'high',
label: '<span>身高<br>(cm)</span>',
align: 'right',
width: '30%',
'min-width': '0.7rem'
},
{
prop: 'gender',
label: '性别',
align: 'right',
width: '20%',
'min-width': '0.7rem'
}
],
tableData: []
};
}
};
</script>
<style scoped>
.table-demo {
background-color: #fff;
padding: 15px;
}
</style>
思考:习惯了UI库的使用,渐渐对组件背后的东西缺乏探索,在写table组件的时候,发现经常使用的组件,其实写起来并不容易,这激起了一丢丢对UI库源码的好奇心,希望我能将这份好奇心付之行动,也希望下次再进行分享时,可以是对某个UI组件源码学习的分享。