Skip to content

Commit

Permalink
wip: Table组件重构中
Browse files Browse the repository at this point in the history
  • Loading branch information
kailong321200875 committed Oct 19, 2021
1 parent 7f5ef99 commit f648424
Show file tree
Hide file tree
Showing 28 changed files with 2,577 additions and 174 deletions.
6 changes: 6 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ declare module 'vue' {
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
Expand All @@ -43,6 +44,8 @@ declare module 'vue' {
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
Expand All @@ -56,7 +59,10 @@ declare module 'vue' {
Qrcode: typeof import('./src/components/Qrcode/index.vue')['default']
Redirect: typeof import('./src/components/Redirect/index.vue')['default']
Search: typeof import('./src/components/Search/index.vue')['default']
Slot: typeof import('./src/components/Table/components/Slot.vue')['default']
SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
Table: typeof import('./src/components/Table/index.vue')['default']
TableColumn: typeof import('./src/components/Table/components/TableColumn.vue')['default']
}
}

Expand Down
37 changes: 37 additions & 0 deletions src/components/Table/components/Slot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script lang="ts">
import { defineComponent, inject, h, PropType } from 'vue'
export default defineComponent({
name: 'Slot',
props: {
row: {
type: Object as PropType<object>,
default: () => null
},
index: {
type: Number as PropType<number>,
default: null
},
column: {
type: Object as PropType<object>,
default: () => null
},
slotName: {
type: String as PropType<string>,
default: ''
}
},
render(props: any) {
const _this: any = inject('tableRoot')
return h(
'span',
_this.slots[props.slotName]({
row: props.row,
column: props.column,
$index: props.index
})
)
}
})
</script>

<style></style>
64 changes: 64 additions & 0 deletions src/components/Table/components/TableColumn.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<template>
<el-table-column v-bind="{ ...getItemBindValue(child) }" :prop="child.key">
<template v-for="item in child.children">
<!-- 树型数据 -->
<template v-if="item.children && item.children.length">
<table-column :key="item[item.field]" :child="item" />
</template>

<template v-else>
<el-table-column
:key="item[item.field]"
v-bind="{ ...getItemBindValue(item) }"
:prop="item.field"
>
<!-- 表头插槽 -->
<template v-if="item.slots && item.slots.header" #header="scope">
<table-slot
v-if="item.slots && item.slots.header"
:slot-name="item.slots.header"
:column="item"
:index="scope.$index"
/>
</template>

<!-- 表格内容插槽自定义 -->
<template v-if="item.slots && item.slots.default" #default="scope">
<table-slot
:slot-name="item.slots.default"
:row="scope.row"
:column="item"
:index="scope.$index"
/>
</template>
</el-table-column>
</template>
</template>
</el-table-column>
</template>

<script setup lang="ts" name="TableColumn">
import { PropType } from 'vue'
import TableSlot from './Slot.vue'
import { deepClone } from '@/utils'
defineProps({
child: {
type: Object as PropType<IObj>,
required: true
}
})
function getItemBindValue(item: any) {
const delArr: string[] = ['children']
const obj = deepClone(item)
for (const key in obj) {
if (delArr.indexOf(key) !== -1) {
delete obj[key]
}
}
return obj
}
</script>

<style></style>
170 changes: 170 additions & 0 deletions src/components/Table/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<template>
<el-table ref="elTable" :border="true" v-bind="getBindValue" @header-dragend="headerDragend">
<!-- 多选 -->
<el-table-column
v-if="selection"
type="selection"
:reserve-selection="reserveSelection"
width="40"
/>
<template v-for="item in columns">
<!-- 自定义索引 -->
<template v-if="item.type === 'index'">
<el-table-column
:key="item[item.field]"
v-bind="{ ...getItemBindValue(item) }"
type="index"
:index="item.index"
/>
</template>

<!-- 树型数据 -->
<template v-else-if="item.children && item.children.length">
<table-column :key="item[item.field]" :child="item" />
</template>

<template v-else>
<el-table-column
:key="item[item.field]"
v-bind="{ ...getItemBindValue(item) }"
:prop="item.field"
>
<!-- 表头插槽 -->
<template v-if="item.slots && item.slots.header" #header="scope">
<table-slot
v-if="item.slots && item.slots.header"
:slot-name="item.slots.header"
:column="item"
:index="scope.$index"
/>
</template>

<!-- 表格内容插槽自定义 -->
<template v-if="item.slots && item.slots.default" #default="scope">
<table-slot
v-if="item.slots && item.slots.default"
:slot-name="item.slots.default"
:row="scope.row"
:column="item"
:index="scope.$index"
/>
</template>
</el-table-column>
</template>
</template>
</el-table>

<div v-if="pagination" class="pagination__wrap">
<el-pagination
:style="paginationStyle"
:page-sizes="[10, 20, 30, 40, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
v-bind="getPaginationBindValue"
@size-change="sizeChange"
@current-change="currentChange"
/>
</div>
</template>

<script setup lang="ts" name="ComTable">
import { PropType, computed, ref, unref, useAttrs } from 'vue'
import { deepClone } from '@/utils'
import { isObject } from '@/utils/validate'
import TableColumn from './components/TableColumn.vue'
import TableSlot from './components/Slot.vue'
const props = defineProps({
// 表头
columns: {
type: Array as PropType<IObj[]>,
default: () => []
},
// 是否多选
selection: {
type: Boolean as PropType<boolean>,
default: false
},
// 是否展示分页
pagination: {
type: [Boolean, Object] as PropType<boolean | IObj>,
default: false
},
// 仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据(需指定 row-key)
reserveSelection: {
type: Boolean as PropType<boolean>,
default: false
}
})
const attrs = useAttrs()
const elTable = ref<HTMLElement | null>(null)
function getTableRef() {
return unref(elTable as any)
}
// const _this = getCurrentInstance()
// provide('tableRoot', _this)
const getBindValue = computed((): IObj => {
const bindValue = { ...attrs, ...props } as IObj
delete bindValue.columns
return bindValue
})
function getItemBindValue(item: IObj) {
const delArr: string[] = []
const obj = deepClone(item)
for (const key in obj) {
if (delArr.indexOf(key) !== -1) {
delete obj[key]
}
}
return obj
}
const getPaginationBindValue = computed((): IObj => {
const PaginationBindValue =
props.pagination && isObject(props.pagination) ? { ...props.pagination } : {}
return PaginationBindValue
})
const paginationStyle = computed(() => {
return {
textAlign: (props.pagination && (props.pagination as IObj).position) || 'right'
}
})
function headerDragend(newWidth: number, _: number, column: IObj) {
// 不懂为啥无法自动计算宽度,只能手动去计算了。。失望ing,到时候看看能不能优化吧。
const htmlArr = document.getElementsByClassName(column.id)
for (const v of htmlArr as any) {
if (v.firstElementChild) {
;(v.firstElementChild as any).style.width = newWidth + 'px'
}
}
}
function sizeChange(val: number) {
if (props.pagination && (props.pagination as IObj).onSizeChange) {
;(props.pagination as IObj).onSizeChange(val)
}
}
function currentChange(val: number) {
if (props.pagination && (props.pagination as IObj).onCurrentChange) {
;(props.pagination as IObj).onCurrentChange(val)
}
}
defineExpose({
getTableRef
})
</script>

<style lang="less" scoped>
.pagination__wrap {
padding: 10px;
margin-top: 15px;
background: #fff;
}
</style>
2 changes: 2 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import SvgIcon from './SvgIcon/index.vue' // svg组件
import ComSearch from './Search/index.vue' // search组件
import ComDialog from './Dialog/index.vue' // dialog组件
import ComDetail from './Detail/index.vue' // detail组件
import ComTable from './Table/index.vue' // table组件

export function setupGlobCom(app: App<Element>): void {
app.component('SvgIcon', SvgIcon)
app.component('ComSearch', ComSearch)
app.component('ComDialog', ComDialog)
app.component('ComDetail', ComDetail)
app.component('ComTable', ComTable)
}
Loading

0 comments on commit f648424

Please sign in to comment.