表格弹窗
表格弹窗,选 Table 数据
基础用法
组件必须使用row-key
属性,用于内部匹配。使用v-model
进行双向绑定。使用config.label
来配置右侧需要展示的内容。
[ { "id": 2, "prop3": "字段3_2" } ]
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
@sure="handleSure"
>
<template #trigger>
<el-button>添加</el-button>
</template>
</ElTableDialog>
<pre>{{ data }}</pre>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([{ id: 2, prop3: '字段3_2' }])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
const handleSure = (values) => {
console.log('sure:', values)
}
</script>
隐藏源代码
头部插入
将新选择项添加到数组头部
vue
<template>
<ElTableDialog
v-model="data"
unshift
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
>
<template #trigger>
<el-button>添加</el-button>
</template>
</ElTableDialog>
<!-- <pre>{{ data }}</pre> -->
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([{ id: 2, prop3: '字段3_2' }])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
</script>
隐藏源代码
单选
使用type="radio"
进行单选
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
type="radio"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
>
<template #trigger>
<el-button>添加</el-button>
</template>
</ElTableDialog>
<!-- <pre>{{ data }}</pre> -->
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([{ id: 2, prop3: '字段3_2' }])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
</script>
隐藏源代码
隐藏右侧选中栏
使用hidden-right
进行隐藏。也支持相关事件 sure
cancel
close
open
,支持Dialog
组件所有事件
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
type="radio"
title="选择客成"
hidden-right
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
height="600px"
@sure="handleEvt('sure')"
@cancel="handleEvt('cancel')"
@close="handleEvt('close')"
@open="handleEvt('open')"
>
<template #trigger>
<el-button>添加</el-button>
</template>
</ElTableDialog>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([{ id: 2, prop3: '字段3_2' }])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
const handleEvt = (evtName) => {
console.log(evtName)
}
</script>
隐藏源代码
宽/高设置
使用height
对 table 的高度进行设置,使用width
属性对整体弹窗的宽度进行设置。
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:pagination="{ defaultPageSize: 20 }"
height="600"
width="1000"
:config="{ label: 'prop1' }"
>
<template #trigger>
<el-button>添加</el-button>
</template>
</ElTableDialog>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
</script>
隐藏源代码
自定义触发器
使用trigger
插槽可以自定义触发器
+ 添加
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop1' }"
>
<template #header>
<p>自定义头部,自行摆放Form组件</p>
</template>
<template #trigger>
<el-tag
v-for="(item, index) in data"
:key="index"
style="margin-right: 8px"
closable
type="primary"
@close.stop="handleDel(index)"
>
{{ item.prop1 }}
</el-tag>
<el-tag type="info">+ 添加</el-tag>
</template>
</ElTableDialog>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([])
const handleDel = (index) => {
data.value.splice(index, 1)
}
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
</script>
隐藏源代码
自定义 Label
使用label
插槽可以自定义右侧选中的 UI
+ 添加
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop1' }"
>
<template #trigger>
<el-tag
v-for="(item, index) in data"
:key="index"
style="margin-right: 8px"
closable
type="primary"
@close.stop="handleDel(index)"
>
{{ item.prop1 }}
</el-tag>
<el-tag type="info">+ 添加</el-tag>
</template>
<template #label="{ item, index, close }">
<div class="item">
<span>{{ item.prop1 }}-{{ index }}</span>
<el-icon @click="close"><CircleClose /></el-icon>
</div>
</template>
</ElTableDialog>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
import { CircleClose } from '@element-plus/icons-vue'
const data = ref([])
const handleDel = (index) => {
data.value.splice(index, 1)
}
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
</script>
<style lang="scss" scoped>
.item {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
padding: 0 12px;
color: red;
span {
color: rgb(96, 98, 102);
}
i {
cursor: pointer;
}
}
</style>
隐藏源代码
自定义 Title
使用title
插槽可以自定义右侧的 title
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
@sure="handleSure"
>
<template #trigger>
<el-button>添加</el-button>
</template>
<template #title="{ selectList, closeDialog }">
<el-flex justify="space-between">
<span>已选择{{ selectList.length }}个</span>
<span @click="closeDialog">关闭</span>
</el-flex>
</template>
</ElTableDialog>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([{ id: 2, prop3: '字段3_2' }])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
const handleSure = (values) => {
console.log('sure:', values)
}
</script>
隐藏源代码
大数据渲染
右侧使用虚拟列表渲染,轻松渲染上千或上万条数据。
vue
<template>
<ElTableDialog
ref="dialogRef"
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
/>
<el-button @click="open">点我打开(建议使用插槽来打开)</el-button>
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const dialogRef = ref()
// const data = ref([{ id: 2, prop3: '字段3_2' }])
const data = ref(
Array.from({ length: 10000 }).map((_, index) => {
return { id: index, prop3: `徐志伟-${index}` }
})
)
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
const open = () => {
dialogRef.value.openDialog()
}
</script>
隐藏源代码
确定按钮-异步处理
使用on-sure
属性处理异步接口
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
:config="{ label: 'prop3' }"
:on-sure="handleSure"
sure-text="提交"
>
<template #trigger>
<el-button>添加</el-button>
</template>
</ElTableDialog>
<!-- <pre>{{ data }}</pre> -->
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
import { ElMessage } from 'element-plus'
const data: any = ref([])
setTimeout(() => {
data.value = [{ id: 2, prop3: '字段3_2' }]
}, 1000)
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
const getDataFormAPI = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const flag = Math.random() > 0.5
return Math.random() > 0.5
? reject('Error')
: resolve({
code: flag ? 1 : 0,
message: flag ? '服务器其他异常情况' : '',
})
}, 1000)
})
}
const handleSure = (data) => {
return getDataFormAPI().then((res: any) => {
console.log(res)
if (res.code === 0) {
ElMessage.success('成功')
} else {
throw new Error(res.message)
}
})
}
</script>
隐藏源代码
top,footer 插槽
使用top
,footer
插槽,来满足更多业务
vue
<template>
<ElTableDialog
v-model="data"
row-key="id"
title="选择客成"
:http-request="getList"
:columns="columns"
hidden-right
type="radio"
:config="{ label: 'prop3' }"
>
<template #trigger>
<el-button>添加</el-button>
</template>
<template #top>
<el-steps style="padding: 0 20px; margin-bottom: 12px">
<el-step title="Step 1" />
<el-step title="Step 2" />
<el-step title="Step 3" />
</el-steps>
</template>
<template #footer>
<div style="display: flex; justify-content: flex-end; padding: 12px">
<el-button> 取消 </el-button>
<el-button type="primary"> 下一步 </el-button>
</div>
</template>
</ElTableDialog>
<!-- <pre>{{ data }}</pre> -->
</template>
<script setup lang="ts">
import { h, ref } from 'vue'
const data = ref([{ id: 2, prop3: '字段3_2' }])
const requestData = (() => {
const f = ({ current: pageNo, size: pageSize, ...args }: any) => {
console.log('参数:', pageNo, pageSize, args)
const total = f.total
return new Promise((resolve) => {
setTimeout(() => {
const totalPages = Math.ceil(total / pageSize)
const size = (pageNo - 1) * pageSize
return resolve({
list: Array.from({
length: pageNo === totalPages ? total % size : pageSize,
}).map((_, index) => {
const base = (pageNo - 1) * pageSize
index = base + index + 1
return {
prop1: `字段1_${index}`,
prop2: `字段2_${index}`,
prop3: `字段3_${index}`,
id: index,
}
}),
total,
})
}, 500)
})
}
f.total = Math.ceil(Math.random() * 1000)
return f
})()
const getList = ({ params, resolve }: any) => {
requestData(params).then((res) => {
resolve(res)
})
}
const columns = [
{
type: 'index',
width: 60,
headerCellRenderer(data: any) {
return h('span', '序号')
},
},
{
label: '联系人',
prop: 'prop1',
},
{
label: '手机号码',
prop: 'prop2',
},
{
label: '分配客成',
prop: 'prop3',
},
]
</script>
隐藏源代码
API
Props
属性名 | 说明 | 类型 | 默认值 |
---|---|---|---|
http-request | 接口请求 | function | - |
columns | el-table-column 组件属性 | Array<TableColumnCtx> | el-table-column 属性+ cellRenderer + headerCellRenderer + reserveRadioSelection |
pagination | el-pagination 组件属性 | PaginationProps | el-pagination 组件属性 + defaultPageSize + showRecord + showTotal |
config | 转换接口入参的 key | Config | { label: 'label'} |
modelValue | 双向绑定的值 | any[] | [] |
rowKey | 行数据的 Key,用来优化 Table 的渲染 | string | - |
title | 弹窗标题 | string | - |
width | 弹窗总体宽度 | string | 900 |
height | 弹窗 table 高度 | string | 500 |
type | 选择类型(checkbox|radio) | string | checkbox |
hidden-right | 是否隐藏右侧选中栏 | boolean | false |
dynamic-size-list-props | 虚拟列表组件属性 | object | { estimatedItemSize: 32, itemSize: () => 32, height: 460, width: 295 } |
on-sure | 处理点击 sure 按钮 | function | {any[], { loading, closeDialog }} |
sure-text | 确定文案 | string | 确定 |
cancel-text | 取消文案 | string | 取消 |
selected-field-title | 已选字段文案 | string | 已选字段 |
Slots
插槽名 | 说明 | 类型 |
---|---|---|
header | 往 table-page 顶部插入内容 | - |
trigger | 触发器插槽 | - |
label | 自定义右侧选中内容 | { item, index, close: () => void } |
top | 顶部内容 | - |
footer | 底部内容 | - |
title | 自定义右侧 title | { selectList, closeDialog } |
left 1.1.1 | 左侧内容 | - |
right 1.1.1 | 右侧内容 | - |
Methods
方法名 | 说明 | 参数 |
---|---|---|
request | 调用接口重新请求数据 | {pageSize, currentPage}, 具体字段根据 config 配置 |
getTable | 获取内置 table 组件实例 | - |
openDialog | 打开弹窗 | - |
closeDialog | 关闭弹窗 | - |
Event(支持 Dialog 组件所有事件)
事件名 | 说明 | 参数 |
---|---|---|
sure | 点击确定时出发 | row[] |
cancel | 点击取消时出发 | - |