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组件源码学习的分享。