好的!以下是基于 Element Plus 的通用 Table 组件,支持列定义、数据源、分页等功能,并通过事件 emit 来进行分页处理。
基于 Element Plus 的 Table 组件
vue
复制代码
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
// 1. 通过props接收列定义、数据源、分页配置
const props = defineProps<{
columns: { key: string; label: string; align?: 'left' | 'center' | 'right' }[]
dataSource: Record<string, any>[]
pagination?: { current: number; pageSize: number; total: number }
}>()
// 2. emit用于分页变更事件触发
const emit = defineEmits<{
(e: 'page-change', page: number): void
}>()
// 3. 管理当前页的内部状态
const currentPage = ref(props.pagination?.current || 1)
// 4. 处理页码切换
const onPageChange = (page: number) => {
currentPage.value = page
emit('page-change', page) // 触发父组件处理逻辑
ElMessage.success(`切换到第 ${page} 页`)
}
</script>
<template>
<div class="table-wrapper">
<!-- 使用Element Plus的el-table组件 -->
<el-table :data="dataSource" style="width: 100%">
<!-- 动态渲染列 -->
<el-table-column
v-for="col in columns"
:key="col.key"
:prop="col.key"
:label="col.label"
:align="col.align || 'left'"
></el-table-column>
</el-table>
<!-- 分页器 -->
<el-pagination
v-if="pagination"
background
layout="prev, pager, next"
:current-page="currentPage"
:page-size="props.pagination.pageSize"
:total="props.pagination.total"
@current-change="onPageChange"
/>
</div>
</template>
<style scoped>
.table-wrapper {
margin-top: 16px;
}
</style>
组件说明:
-
props:columns:定义表格的列,包括key、label(显示的名称)和align(对齐方式)。dataSource:表格的数据源,类似于二维数组,每一行数据是一个对象。pagination:分页配置,包括当前页current、每页显示条数pageSize和总数据量total。
-
分页处理:
- 使用
Element Plus的el-pagination组件进行分页,并通过@current-change事件监听页码变化,触发page-change事件传递给父组件。
- 使用
-
列渲染:
- 使用
Element Plus的el-table-column动态生成表格列,根据传入的columns配置渲染不同的列名和数据。
- 使用
使用示例:
在父组件中,你可以这样使用该通用 Table 组件:
vue
复制代码
<template>
<Table
:columns="columns"
:dataSource="data"
:pagination="pagination"
@page-change="handlePageChange"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Table from './Table.vue'
// 列定义
const columns = [
{ key: 'name', label: '名称' },
{ key: 'age', label: '年龄', align: 'center' },
{ key: 'address', label: '地址', align: 'right' },
]
// 模拟的数据源
const data = [
{ name: '张三', age: 25, address: '北京市' },
{ name: '李四', age: 30, address: '上海市' },
]
// 分页配置
const pagination = ref({
current: 1,
pageSize: 10,
total: 100,
})
// 处理分页变化
const handlePageChange = (page) => {
console.log(`切换到第 ${page} 页`)
// 更新数据源的逻辑
}
</script>
说明:
Element Plus提供了丰富的 UI 组件,使得表格和分页的实现更加简洁,并且提供了强大的样式和交互支持。
4o
您说:
再写个Modal和TagInput
ChatGPT 说:
ChatGPT
好的!以下是基于 Element Plus 实现的 Modal 和 TagInput 通用组件示例。
Modal 通用组件
Modal.vue 是一个通用模态框组件,支持通过 props 传入标题和显示状态,并通过 emit 事件控制模态框的显示与隐藏。
vue
复制代码
<script setup lang="ts">
import { ref } from 'vue'
// 1. 通过 props 接收标题和模态框显示状态
const props = defineProps<{
title: string
visible: boolean
}>()
// 2. emit 用于关闭模态框的事件
const emit = defineEmits<{
(e: 'update:visible', visible: boolean): void
}>()
// 3. 控制模态框的关闭逻辑
const closeModal = () => {
emit('update:visible', false) // 将 visible 设为 false 来关闭模态框
}
</script>
<template>
<el-dialog :visible="props.visible" :title="props.title" @close="closeModal">
<slot></slot>
<template #footer>
<el-button @click="closeModal">取消</el-button>
<el-button type="primary" @click="closeModal">确定</el-button>
</template>
</el-dialog>
</template>
使用说明:
-
props接收:title:模态框的标题。visible:控制模态框的显示和隐藏。
-
emit:update:visible:当关闭模态框时,触发事件将visible设置为false,从而隐藏模态框。
父组件中的使用示例:
vue
复制代码
<template>
<el-button @click="openModal">打开模态框</el-button>
<Modal :title="'示例模态框'" :visible="isModalVisible" @update:visible="isModalVisible = $event">
<p>模态框的内容</p>
</Modal>
</template>
<script setup>
import { ref } from 'vue'
import Modal from './Modal.vue'
const isModalVisible = ref(false)
const openModal = () => {
isModalVisible.value = true
}
</script>
<template>
</template>
<script lang="ts" setup>
import { ref,toRefs} from 'vue';
import moment from 'moment'
import { getTitleLevelStr,getSignDurationInter } from '../../../utils/base'
const emit = defineEmits(['orderTalentList','deleteActive','deleteDisable','onEdit'])
const props = defineProps<{
tableData:{
type:DataItem[],
default:[]
}
}>()
const {tableData} = toRefs(props)
//编辑订单
const edit = (record) => {
emit("onEdit",record)
}
//选中的合同
const contractIds = ref([])
const rowSelection = ref({
checkStrictly: false,
onChange: (selectedRowKeys: (string | number)[], selectedRows: DataItem[]) => {
contractIds.value = selectedRowKeys
if(contractIds.value.length!=0){
emit('deleteActive')
}else{
emit('deleteDisable')
}
},
onSelect: (record: DataItem, selected: boolean, selectedRows: DataItem[]) => {
// console.log(record, selected, selectedRows);
},
onSelectAll: (selected: boolean, selectedRows: DataItem[], changeRows: DataItem[]) => {
// console.log(selected, selectedRows, changeRows);
},
});
// 表格分页
const pagination = ref({
current: 1,
pageSize: 10,
total: undefined,
})
// 分页查询订单列表
const onPagination = (page) => {
pagination.value.current = page;
emit("orderTalentList")
}
defineExpose({
pagination,
contractIds
})
</script>
<script setup lang="ts">
defineProps<{
options: { label: string; value: number | string }[]
modelValue?: number | string
}>()
defineEmits<{
(e: 'update:modelValue', value: number | string): void
}>()
</script>
<template>
<div class="cp-radio-btn">
<a
class="item"
href="javascript:;"
v-for="item in options"
:key="item.value"
:class="{ active: item.value === modelValue }"
@click="$emit('update:modelValue', item.value)"
>
{{ item.label }}
</a>
</div>
</template>
<style lang="scss" scoped>
.cp-radio-btn {
display: flex;
flex-wrap: wrap;
.item {
height: 32px;
min-width: 60px;
line-height: 30px;
padding: 0 14px;
text-align: center;
border: 1px solid var(--cp-bg);
background-color: var(--cp-bg);
margin-right: 10px;
box-sizing: border-box;
color: var(--cp-text2);
margin-bottom: 10px;
border-radius: 4px;
transition: all 0.3s;
&.active {
border-color: var(--cp-primary);
background-color: var(--cp-plain);
}
}
}
</style>
<!-- <script setup lang="ts">
// 计数器
// 通过 v-model 解析成 modelValue @update:modelValue
defineProps<{
modelValue: number
}>()
defineEmits<{ (e: 'update:modelValue', count: number): void }>()
</script>
<template>
<div class="cp-radio-btn">
计数器:{{ modelValue }}
<button @click="$emit('update:modelValue', modelValue + 1)">+1</button>
</div>
</template>
<style lang="scss" scoped></style> -->
<!-- <script setup lang="ts">
// 计数器
// 通过 v-model:count 解析成 count @update:count
defineProps<{
count: number
}>()
defineEmits<{ (e: 'update:count', count: number): void }>()
</script>
<template>
<div class="cp-radio-btn">
计数器:{{ count }}
<button @click="$emit('update:count', count + 1)">+1</button>
</div>
</template>
<style lang="scss" scoped></style> -->