优化表单交互:在 el-select 组件中嵌入表格显示选项

介绍了一种通过 el-select 插槽实现表格样式数据展示的方案,可更直观地辅助用户选择。支持列配置、行数据绑定及自定义搜索,简洁高效,适用于复杂选择场景。完整代码见GitHub 仓库。

背景

在进行业务开发选择订单时,如果单纯的根据单号是无法编写是哪一条订单的,这个时候就可以通过表格的方式去展示这条订单的其他信息,辅助用户分辨出订单,不用再去查,更快速、更友好。

效果如下:

el-select-table-click-demo

实现

环境与依赖

  • node 22
  • vue 3
  • element-plus

思路

原理很简单,利用插槽。

虽然通过 el-table 可以实现表格效果,但对这种简单需求来说过于臃肿。而直接使用原生 table 标签结构实现太过于繁琐,不便于实现遍历 el-option

<el-select>
    <!-- 表头,遍历 -->
    <!-- 表体,遍历 -->
    <el-option>
    	<!-- 行数据,遍历 -->
    </el-option>
</el-select>

因此,我采用列表结构实现,结合 CSS 美化出表格效果。具体做法是遍历「列配置」生成表头,再遍历「options」生成行数据。

<el-select 
  ref="inputRef" 
  v-model="selectValue"
  clearable
  filterable
  :placeholder="placeholder" 
  :disabled="disabled" 
  :filter-method="filterMethod" 
  @change="handleChange"
>
  <!-- 表头 -->
  <ul class="select-ul">
    <li v-for="column in columnConfig" :key="column.label">{{ column.label }}</li>
  </ul>
  <el-option v-for="item in showOptions" :key="item[keyNameCom]" :value="item[valueName]">
    <ul class="select-ul select-ul-data">
      <li v-for="column in columnConfig" :key="column.label">{{ item[column.prop] }}</li>
    </ul>
  </el-option>
</el-select>

其中,el-option 的数据绑定属性名默认是 id,可通过配置修改。同时,遍历 key 属性支持自定义,若为空则默认使用 value 属性名,减少额外数据处理。

如何使用

一个简单演示。

  • options:行数据
  • columnConfig:列配置

template 结构和 js 部分如下:

<BaseTableSelect 
  v-model="selectValue" 
  :options="options" 
  :columnConfig="columnConfig" 
>
</BaseTableSelect>
const options = ref([
  {id: "213", department: '古典风格号', createTime: '2024-12-23', place: '学校'},
  {id: "546", department: '都听好', createTime: '2024-12-23', place: '家里'},
  {id: "345", department: '按时到岗', createTime: '2024-12-23', place: '医院'}
])

const columnConfig = ref([
  {label: '单号', prop: 'id'},
  {label: '部门', prop: 'department'},
  {label: '时间', prop: 'createTime'},
  {label: '地点', prop: 'place'},
])

自定义全表格搜索

el-select-table-input-filter-demo

组件 el-select 默认的搜索功能只会根据 label 属性的值去搜索,在表格展示的场景下并不符合,因此需要用到 filter-method 自定义搜索方法属性。

初步简单实现可使用 JSON.stringify() 将选项对象转为字符串,并检测是否包含搜索关键词:

const filterMethod = queryString => {
  showOptions.value = props.options.filter(item => (JSON.stringify(item).includes(queryString) ? true : false))
}

不过,这种方式会将未展示的属性也纳入搜索,导致结果不准确。因此,优化后的搜索方法仅匹配已展示的列数据:

const filterMethod = queryString => {
  if (!queryString) {
    showOptions.value = props.options;
    return;
  }

  showOptions.value = props.options.filter(item => {
    // 针对每个要过滤的列进行判断
    return props.columnConfig.some(config => {
      const propValue = item[config.prop];
      // 将属性值转换为字符串并检查是否包含查询字符串
      return propValue && propValue.toString().includes(queryString);
    });
  });
}

扩展

本文提供的是基础实现。如果需要进一步功能扩展,例如控制搜索功能 (filterable) 或其他交互行为,可通过额外配置实现。但基础版本已满足我的需求,便不写太多不利于阅读代码。

组件代码

仓库:🔗 el-select-table-option

<template>
  <el-select 
    ref="inputRef" 
    v-model="selectValue"
    clearable
    filterable
    :placeholder="placeholder" 
    :disabled="disabled" 
    :filter-method="filterMethod" 
    @change="handleChange"
  >
    <!-- 表头 -->
    <ul class="select-ul">
      <li v-for="column in columnConfig" :key="column.label">{{ column.label }}</li>
    </ul>
    <el-option v-for="item in showOptions" :key="item[keyNameCom]" :value="item[valueName]">
      <ul class="select-ul select-ul-data">
        <li v-for="column in columnConfig" :key="column.label">{{ item[column.prop] }}</li>
      </ul>
    </el-option>
  </el-select>
</template>

<script setup>
import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'

defineOptions({
  name: 'BaseTableSelect'
})

const emit = defineEmits(['update:modelValue', 'keyup-enter', 'focus', 'change'])

const props = defineProps({
  modelValue: null,
  disabled: {
    type: Boolean,
    default: false
  },
  placeholder: {
    type: String,
    default: '请选择'
  },
  /* 列配置 */
  columnConfig: {
    type: Array,
    default(rawProps) {
      return []
    }
  },
  options: {
    type: Array,
    default(rawProps) {
      return []
    }
  },
  valueName: {
    type: String,
    default: 'id'
  },
  keyName: {
    type: String,
    default: ''
  }
})

const selectValue = computed({
  get: () => props.modelValue,
  set: val => {
    emit('update:modelValue', val)
  }
})

// 实际 keyName
// 优先使用 keyName,keyName 为空时,使用 valueName
const keyNameCom = computed(() => {
  return props.keyName !== '' ? props.keyName : props.valueName
})

const handleChange = val => {
  emit('change', val)
}


// ref
const inputRef = ref(null)

// 渲染用的options
const showOptions = ref(props.options)
watch(
  () => props.options,
  newValue => {
    showOptions.value = newValue
    selectValue.value = ''
  },
)
// 筛选
const filterMethod = queryString => {
  if (!queryString) {
    showOptions.value = props.options;
    return;
  }

  showOptions.value = props.options.filter(item => {
    // 针对每个要过滤的列进行判断
    return props.columnConfig.some(config => {
      const propValue = item[config.prop];
      // 将属性值转换为字符串并检查是否包含查询字符串
      return propValue && propValue.toString().includes(queryString);
    });
  });
}

// 得到焦点
const getFocus = () => {
  nextTick(() => {
    inputRef.value.focus()
  })
}

defineExpose({
  getFocus
})
</script>

<style lang="scss" scoped></style>
<style scoped lang="scss">
.select-ul {
  padding-right: 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
  text-align: center;
  padding-inline-start: 0;
  padding: 0 20px;
  > li {
    display: inline-block;
    width: 100px;
    // margin: 6px;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
.el-select-dropdown__item {
  padding: 0;
}
</style>

属性

参数说明类型默认值
disabled是否禁用booleanfalse
placeholder请选择string‘请选择’
columnConfig列配置,[{label: ‘’, prop: ‘’}]array[]
options选项array[]
valueName选项值的属性名string‘id’
keyName遍历选项时的 keystring‘’

参考

首发地址:https://blog.xchive.top/2024/optimizing-form-interactions-embedding-table-display-options-in-el-select-components.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/920479.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot中设置超时30分钟自动删除元素的List和Map

简介 在 Spring Boot 中&#xff0c;你可以使用多种方法来实现自动删除超时元素的 List 或 Map。以下是两种常见的方式&#xff1a; 如果你需要简单的功能并且不介意引入外部依赖&#xff0c;可以选择 Guava Cache。如果你想要更灵活的控制&#xff0c;使用 Spring 的调度功能…

使用可视化工具kafkatool连接docker的kafka集群,查看消息内容和offset

1、下载kafkatool 下载地址Offset Explorer&#xff0c;下载对应系统的offset explorer 下载完&#xff0c;傻瓜安装即可&#xff08;建议放D盘&#xff09;&#xff0c;在开始菜单输入offset找到该应用打开 打开 2、连接kafka 点击File > add new connection Bootstrap…

Docker3:docker基础1

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

BLIP-2模型的详解与思考

大模型学习笔记------BLIP-2模型的详解与思考 1、BLIP-2框架概述2、BLIP-2网络结构详解3、BLIP-2的几点思考 上一篇文章上文中讲解了 BLIP&#xff08;Bootstrapping Language-Image Pretraining&#xff09;模型的一些思考&#xff0c;本文将讲述一个BLIP的升级版 BLIP-2&am…

java-贪心算法

1. 霍夫曼编码&#xff08;Huffman Coding&#xff09; 描述&#xff1a; 霍夫曼编码是一种使用变长编码表对数据进行编码的算法&#xff0c;由David A. Huffman在1952年发明。它是一种贪心算法&#xff0c;用于数据压缩。霍夫曼编码通过构建一个二叉树&#xff08;霍夫曼树&a…

RK3568平台(中断篇)ARM中断流程

一.ARM 处理器程序运行的过程 ARM芯片属于精简指令集计算机 (RISC: Reduced Instruction Set Computing),它所用的指令比较简单,有如下特点: ① 对内存只有读、写指令 ② 对于数据的运算是在CPU内部实现 ③ 使用RISC指令的CPU复杂度小一点,易于设计 比如对于 a=a+b 这…

SpringBoot与MongoDB深度整合及应用案例

SpringBoot与MongoDB深度整合及应用案例 在当今快速发展的软件开发领域&#xff0c;NoSQL数据库因其灵活性和可扩展性而变得越来越流行。MongoDB&#xff0c;作为一款领先的NoSQL数据库&#xff0c;以其文档导向的存储模型和强大的查询能力脱颖而出。本文将为您提供一个全方位…

项目实战(webshop)

一、搭建靶场webshop(www.example1.com) 二、信息收集 1、获取IP winR→cmd→ping www.example1.com→显示出ip(192.168.51.128) 注&#xff1a;TTL为IP包的生存时间&#xff0c;拿到TTL我们可以大概的判断一下目标机器的操作系统&#xff0c;但不是很准确&#xff0c;因为…

初识算法 · 分治(3)

目录 前言&#xff1a; 归并排序 题目解析 算法原理 算法编写 求逆序对总数 题目解析 算法原理 算法编写 前言&#xff1a; ​本文的主题是分治&#xff0c;通过两道题目讲解&#xff0c;一道是归并排序&#xff0c;一道是求逆序对。 链接分别为&#xff1a; 912. 排…

MyBatis——#{} 和 ${} 的区别和动态 SQL

1. #{} 和 ${} 的区别 为了方便&#xff0c;接下来使用注解方式来演示&#xff1a; #{} 的 SQL 语句中的参数是用过 ? 来起到类似于占位符的作用&#xff0c;而 ${} 是直接进行参数替换&#xff0c;这种直接替换的即时 SQL 就可能会出现一个问题 当传入一个字符串时&#xff…

学习threejs,导入FBX格式骨骼绑定模型

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.FBXLoader fbx 模型加…

【腾讯云产品最佳实践】腾讯云CVM入门技术与实践:通过腾讯云快速构建云上应用

目录 前言 什么是腾讯云CVM&#xff1f; 腾讯云CVM的技术优势 基于最佳技术实践&#xff0c;使用腾讯云CVM搭建应用 1. 开通CVM实例 2. 连接CVM实例 3. 配置Web环境 4. 部署PHP应用 腾讯云CVM行业应用案例&#xff1a;电商平台的双十一攻略 1. 弹性伸缩解决高并发问题…

mongodb多表查询,五个表查询

需求是这样的&#xff0c;而数据是从mysql导入进来的&#xff0c;由于mysql不支持数组类型的数据&#xff0c;所以有很多关联表。药剂里找药物&#xff0c;需要药剂与药物的关联表&#xff0c;然后再找药物表。从药物表里再找药物与成分关联表&#xff0c;最后再找成分表。 这里…

STL中vector实现——简单易懂版

本章内容 模拟实现 vector 的部分重要功能 1.迭代器的引入1.1 之前写法1.2 STL库中的写法 2.默认成员函数2.1构造与拷贝构造2.2拷贝赋值2.3析构函数 3.增删查改功能3.1插入3.2删除 4.为什么STL中vector没有find函数&#xff1f;5.&#x1f525;&#x1f525;迭代器失效场景&am…

Springboot + vue 健身房管理系统项目部署

1、前言 ​ 许多人在拿到 Spring Boot 项目的源码后&#xff0c;不知道如何运行。我以 Spring Boot Vue 健身房管理系统的部署为例&#xff0c;详细介绍一下部署流程。大多数 Spring Boot 项目都可以通过这种方式部署&#xff0c;希望能帮助到大家。 ​ 2、项目查看 ​ 首…

NuGet如何支持HTTP源

今天是2024年11月21号&#xff0c;最近更新了VisualStudio后发现HTTP的包源已经默认禁止使用了&#xff0c;生成时会直接报错。如下图&#xff1a; 官方也明确指出了要想使用HTTP包源的解决办法&#xff0c;这里就简单总结一下。 一、全局配置 1、全局NuGet包的配置文件路径在…

SpringBoot学习记录(四)之分页查询

SpringBoot学习记录&#xff08;四&#xff09;之分页查询 一、业务需求1、基本信息2、请求参数3、相应数据 二、传统方式分页三、使用PageHelper分页插件 一、业务需求 根据条件进行员工数据的条件分页查询 1、基本信息 请求路径&#xff1a; /emps 请求方式&#xff1a; …

JavaParser如何获取方法的返回类型

使用JavaParser 如何获取一个Java类中的某个方法的返回类型呢&#xff1f; 假如有一个如下的简单的Java 类&#xff1a; /*** Copyright (C) Oscar Chen(XM):* * Date: 2024-11-21* Author: XM*/ package com.osxm.ai.sdlc.codeparse.codesample;public class MyClass {public…

2024亚太杯国际赛C题宠物预测1234问完整解题思路代码+成品参考文章

中国宠物业发展趋势及预测模型 一、问题背景与研究目标 近年来&#xff0c;中国宠物业经历了快速发展&#xff0c;特别是在城市化进程加快、人口结构变化和消费水平提升的背景下&#xff0c;宠物作为家庭成员的角色变得愈发重要。根据相关数据&#xff0c;中国宠物数量&#…

Java实现离线身份证号码OCR识别

最近公司要求做离线身份证OCR功能&#xff0c;找了一圈总算是找到了&#xff0c;在这里对文档做个整理&#xff0c;方便后来者&#xff0c;感谢码龄23年博主的分享 系统&#xff1a;Windows11&#xff0c;红旗Linux Asianux8.1 文档中Linux全root用户操作&#xff1b;需先安装…