上次客户过来讨论的时候,说起其旧系统很多字段选择是通过弹出表格选择记录的,希望沿袭这个使用习惯,否则客户对新系统开发可能不适应,问我如何在Vue3+ElementPlus前端中是否可以实现,我说你基于JQuery的都可以实现,那么Vue3上开发肯定没问题的,而且响应会更加丝滑的,于是我就琢磨做一个通用的案例,整合在我的SqlSugar开发框架的Vue3+ElementPlus前端中。既然要弄就弄个通用的自定义表格选择组件,以便在更多的场合下可以使用,通过动态配置表格字段和相关的属性即可显示和选择。

本篇例子结合Popover 弹出框和Input输入框实现用户记录的选择,以及结合Popover 弹出框和按钮选择实现菜单中多语言键值的选择两项功能实现进行介绍。

1、结合Popover 弹出框和Input输入框实现表格记录选择

在el-Popover的组件中,我们也都看到了他的一个弹出表格的简单案例,如下所示。

不过这个例子太过简单,参考下可以,但是和我们实现通用的数据记录查询以及表格内容可以变化等需求不符合,我们需要根据这样的模式,把Input输入和表格显示整合到里面去,这样可以在对应的表格上进行数据查询过滤,这样可以快速选择到记录。

我的大概需求如下:

使用 Vue 3 + Element Plus 实现的自定义组件示例,它可以用在不同的业务表中,要求通用化,功能上它集成了:

  • el-popover 弹出框,用于显示选择面板

  • el-input 输入框,点击触发弹出

  • el-table 表格控件,展示可选项,还可以对数据进行过滤查询

  • 可点击表格行来选择记录并回填到输入框中

该组件适用于选择一个记录项(如客户、产品等)并回传给父组件。

你可以根据需要扩展以下功能:

  • 支持远程搜索(使用 el-table@filter-change 或增加 el-input 搜索框)

  • 支持分页(结合 el-pagination

  • 支持多选(表格加 type="selection",回传数组)

  • 支持懒加载(点击时加载 options)

我们先来看看成品的效果,下面案例是我基于用户记录表进行选择的处理下效果。

单击选择用户的输入框,就会弹出对应的数据表格进行显示,我们可以在其中进行过滤查询,然后单击记录可以选中返回。

我们自定义组件名称命名为 TableSelector,那么它的使用代码如下所示。

<el-form-item label="选择用户名">
<TableSelector
v-model="selectedUser"
filter-placeholder="请输入人员编号/姓名/电话/住址等搜索"
:columns="[
{ prop: 'id', label: 'ID', width: 80 },
{ prop: 'name', label: '用户名' },
{ prop: 'fullname', label: '真实姓名' },
{ prop: 'mobilephone', label: '移动电话' },
{ prop: 'email', label: '邮箱' }
]"
:fetchData="loadUsers"
row-key="name"
placeholder="请选择用户"
/>
</el-form-item>

v-model绑定选中的记录对象,其中 columns 属性我们可以根据不同的业务表进行配置显示,而 fetchData 则是传入一个函数给它获取数据的,交给调用的父组件进行数据的过滤和处理即可。

其中的loadUsers的实现,我们根据不同的业务实现它的数据请求查询即可,如下是函数代码。

//加载用户,供选择表格处理
async function loadUsers(filter: string) {
const params = {
maxresultcount: 100,
skipcount: 0,
sorting: '',
filter: filter
};
const res = await user.GetAllByFilter(params);
return res.items;
}

这样我们就可以实现通用的处理,不同的业务记录显示,我们配置表格内容显示和获取数据的逻辑即可。

自定义组件的props定义和emits事件如下所示。

// Props
const props = defineProps<{
columns: ColumnDef[];
data?: any[];
modelValue?: any | any[]; // 当前选中值(单个对象或数组)
rowKey?: string; // 要显示的字段 key(如 name)
multiple?: boolean;
pagination?: {
page: number;
pageSize: number;
total: number;
onPageChange: (page: number) => void;
};
fetchData?: (filter: string) => Promise<any[]>; // 外部提供的数据加载函数
placeholder?: string;
filterPlaceholder?: string;
}>(); // Emits
const emit = defineEmits<{
(e: 'update:modelValue', val: any | any[]): void;
}>();

我们为了剥离具体表格字段的处理,因此配置了动态的columns参数,因此在自定义组件显示表格的时候,根据配置的信息进行显示字段即可,如下所示。

<template>
<div>
<el-popover
v-model:visible="visible"
placement="bottom-start"
width="600"
trigger="focus"
:teleported="false"
>
<div style="margin-bottom: 8px">
<el-input
v-model="filterText"
:placeholder="filterPlaceholder || '输入关键字筛选'"
clearable
/>
</div>
<!-- 表格区域 -->
<el-table
v-loading="loading"
:data="tableData"
:height="300"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
:row-key="rowKey"
:highlight-current-row="isSingleSelect"
style="width: 100%"
>
<el-table-column v-if="multiple" type="selection" width="40" />
<template v-for="col in columns" :key="col.prop">
<el-table-column
:prop="col.prop"
:label="col.label"
:width="col.width"
/>
</template>

</el-table>

在输入框的处理上,我们设置它的显示内容和清空按钮等处理,如下所示。

      <!-- 弹出内容插槽的触发器 -->
<template #reference>
<el-input
v-model="displayText"
readonly
:placeholder="placeholder || '请选择...'"
suffix-icon="el-icon-arrow-down"
@click.stop="visible = true"
:clearable="true"
>
<template #suffix>
<el-icon
v-if="displayText"
class="cursor-pointer"
@click.stop="clearSelection"
>
<CircleClose />
</el-icon> </template
></el-input>
</template>

而且输入框里面的显示displaytext是根据选中记录的属性进行计算显示的,如下代码所示。

const displayText = computed(() => {
const data = props.modelValue;
if (!data) return '';
if (Array.isArray(data)) {
return data.map(v => v?.[props.rowKey || 'id']).join(', ');
}
return data?.[props.rowKey || 'id'] || '';
});

通过对显示和过滤的属性进行监控,我们可以对数据的加载逻辑进行处理,从而实现数据的动态展示和过滤。

const loadData = async () => {
loading.value = true;
try {
if (props.fetchData) {
tableData.value = await props.fetchData(filterText.value);
} else if (props.data) {
tableData.value = props.data;
} // 恢复选中状态(仅多选模式)
if (props.multiple && Array.isArray(props.modelValue)) {
selectedRows.value = props.modelValue;
}
} finally {
loading.value = false;
}
}; watch(
() => visible.value,
async val => {
if (val) {
loadData();
}
}
); // 输入过滤条件时防抖加载
watch(
filterText,
debounce(() => {
if (visible.value) loadData();
}, 300)
);

我们也可以使用它实现多选记录的处理,多选提供复选框选择多个记录,并通过确认按钮返回,如下所示。

2、结合Popover 弹出框和按钮选择实现菜单中多语言键值的选择

除了上面通过输入框的方式进行弹出表格数据供用户选择外,有时候我们想在不影响常规输入框的情况下,提供一个额外的按钮,触发弹出选择记录的对话框。

如下面案例,我需要把多语言的键值列出来供我们定义菜单的或者一些界面元素的名称,界面效果如下所示。

选中后,我们就可以及时的显示多语言的键和对应的语言内容了。

上面的自定义控件的使用代码如下所示。

  <el-form-item label="显示名称" prop="name" class="flex flex-row">
<el-input v-model="editForm.name" style="width: 180px" />
<TableSelectorButton
v-model="selectedLocal"
filter-placeholder="请输入键名搜索"
:columns="[
{ prop: 'key', label: '语言键名' },
{ prop: 'text', label: '国际化名称' }
]"
:fetchData="loadLocals"
row-key="key"
@update:model-value="updateLocaleName"
></TableSelectorButton>
</el-form-item>

通过对事件

@update:model-value="updateLocaleName"

进行跟踪,我们就可以在内容变化的时候,及时通知其他控件进行内容更新了。

上面的多语言处理和选择用户的输入框控件很相似,只是为了可以不影响输入框的可编辑性,我们通过按钮来选择在某些场合可能更为合理,因此扩展了这个选择组件,他们的差异只是把输入框换为按钮的处理,如下代码。

      <!-- 弹出内容插槽的触发器 -->
<template #reference>
<el-button
:type="props.buttonType || 'primary'"
class="m-2"
round
plain
>
{{ props.buttonText || '...' }}
</el-button>
</template>

这样我们定义的属性中,需要增加按钮的类型Type和按钮的名称来自定义即可,其他属性不变。

// Props
const props = defineProps({
columns: {
type: Array as PropType<ColumnDef[]>,
required: true
},
data: {
type: Array as PropType<any[]>,
required: false
},
modelValue: {
type: [Object, Array] as PropType<any | any[]>, // 可以是对象或数组
required: false
},
rowKey: {
type: String,
required: false
},
multiple: {
type: Boolean,
required: false
},
pagination: {
type: Object as PropType<{
page: number;
pageSize: number;
total: number;
onPageChange: (page: number) => void;
}>,
required: false
},
fetchData: {
type: Function as PropType<(filter: string) => Promise<any[]>>,
required: false
},
buttonText: {
type: String,
required:
false
},
buttonType: {
type: String as PropType<'default' | 'text' | 'success' | 'primary' | 'warning' | 'info' | 'danger'>,
required: false

},

filterPlaceholder: {
type: String,
required: false
}
});

以上两个例子,都是基于Popover 弹出框进行的自定义控件封装,主要就是为用户选择其他表或记录更加友好 ,从而快速实现数据的查询和选择处理的过程。

熟悉对前端自定义控件的封装,可以根据我们实际业务的需求进行界面逻辑的抽离和重用,实现统一化的界面效果处理。

在Vue3+ElementPlus前端中增加表格记录选择的自定义组件,通过结合Popover 弹出框和Input输入框或者按钮选择实现的更多相关文章

  1. easyui tree datagrid动态添加表头和表格数据,动态弹出框,修改和删除按钮

    1.要有获取表头的URL和表格的URL 背景:点击树的一个节点,就加载一个表格,这个表格是动态的,表头和表格数据都是动态的 解决方案:需要两个URL,一个是获取表头的URL,一个是获取表格数据的URL ...

  2. php中bootstrap框架.popover弹出框,鼠标移动到上面自动显示,离开自动消失

    <div rel="name"></div> <script> $(function(){//显示弹出框 $("[rel=name]& ...

  3. Mint-ui 中 Popup 作为组件引入,控制弹出框的显示与隐藏遇到的问题。

    Popup组件的结构: <template>   <div>   <!--分享弹出窗 begin-->     <mt-popup class="s ...

  4. android中怎么把自己须要的app启动图标集中到一个弹出框中

    先看效果图 这个是我们自己的apk点击之后的效果 下边是布局文件 activity_main.xml主布局文件 <LinearLayout xmlns:android="http:// ...

  5. 苹果手机iOS11中fixed弹出框中input光标错位问题

    最近遇到了一个移动前端的BUG:手机弹出框中的输入框focus时光标可能会错位. 刚开始时我完全不知道错误原因是什么,在电脑上调试时完全没有问题,手机上出现问题时也没有找到规律.后来在网上搜索了大量的 ...

  6. bootstrap中popover.js(弹出框)使用总结+案例

    bootstrap中popover.js(弹出框)使用总结+案例 *转载请注明出处: 作者:willingtolove: http://www.cnblogs.com/willingtolove/p/ ...

  7. 弹出框页面中使用jquery.validate验证控件

    弹出框页面中使用jquery.validate验证控件有几个问题需要解决: 1,弹出框的提交事件完成后如何关闭弹出框页面? 2,提交不成功如何返回当前页? 3,如果知道验证事件成功? 之前笔者都是JS ...

  8. [js]uploadify结合jqueryUI弹出框上传,js中的冒出的bug,又被ie坑了

    引言 最近在一个项目中,在用户列表中需要对给没有签名样本的个别用户上传签名的样本,就想到博客园中上传图片使用弹出框方式,博客园具体怎么实现的不知道,只是如果自己来弄,想到两个插件的结合使用,在弹出框中 ...

  9. 自设table表格,获取内容,并经弹出框的url传参,获取结果显示在弹出框,并加载合计

    table表格,选择框 form id="editForm1"> <table class="table_form"> <td > ...

  10. 在ASP.NET MVC4中实现同页面增删改查,无弹出框02,增删改查界面设计

    在上一篇"在ASP.NET MVC4中实现同页面增删改查,无弹出框01,Repository的搭建"中,已经搭建好了Repository层,本篇就剩下增删改查的界面了......今 ...

随机推荐

  1. 原生JS表格数据常用总结

    主要是在数据报表这块, 做了好几年发现, 其实用户最终想要看的并不是酷炫的BI大屏, 而是最基础也是最复杂的 中国式报表. 更多就是倾向于从表格中去获取数据信息, 最简单的就是最好的, 于是还是来总结 ...

  2. vue3 基础-生命周期函数

    在 vue 中, 生命周期函数可理解为 "在某个时刻, 会自动执行的函数". 先直观感受一下图示. 一共就八个: <!DOCTYPE html> <html la ...

  3. OpenPPL的执行流程与类间关系UML表达

    上一讲,对OpenPPL进行了介绍,以及通过官方文档,学习了它的python与C++的操作流程,以及如添加新的引擎与Op算子. 本节,将通过阅读代码通过UML梳理操作流程以及类之间的相互关系 src地 ...

  4. codeup之日期类

    Description 编写一个日期类,要求按xxxx-xx-xx 的格式输出日期,实现加一天的操作. Input 输入第一行表示测试用例的个数m,接下来m行每行有3个用空格隔开的整数,分别表示年月日 ...

  5. 【异常总结】SeaTunnel集群脑裂配置优化方法

    集群配置 项目 描述 数量 3台 规格 阿里云ECS 16C64G Slot模式 静态50个 ST内存配置 -Xms32g -Xmx32g -XX:MaxMetaspaceSize=8g 异常问题 4 ...

  6. MySQL聚集索引与辅助索引的区别

       聚集索引也称聚簇索引,英文为clustered index.从物理存储角度来分, 索引可以分为聚集索引和辅助索引(secondary index,也称作非聚簇索引),区别主要看叶子节点存了什么数 ...

  7. python库使用总结

    python库的使用 1:print(补充) 2:math 2.1:math库包括的4个数学常数 2.2math库中的函数 幂对数函数 三角曲线函数 3:字符串处理函数 补充:sorted(str) ...

  8. python基础—数字,字符串练习题

    1.如有以下变量 n1=5,请使用 int 的提供的方法,得到该变量最少可以用多少个二进制位表示? n1=5 r=n1.bit_lenght() #当前数字的二进制,至少用n位表示.bit_lengh ...

  9. MCP赋能,给Cursor插上“外挂翅膀”:实战操作数据库

    先给大家个例子, 展示如何用mcp如何带飞cursor的.  话不多说,  继续展示 1.建立项目 提示词如下: " 新建个java项目, 叫user-demo,  通过spring boo ...

  10. 树结构Tree

    树结构 平衡顺序二叉树 通过平衡顺序二叉树查数据的时候,也就等同于二分查找的操作 Binary Search 2,3树 二三树 二三树有 node2 和 node3 两种节点,树的规则如图 2-3-4 ...