惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cisco Blogs
Cyberwarzone
Cyberwarzone
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
SecWiki News
SecWiki News
Martin Fowler
Martin Fowler
T
Tor Project blog
N
Netflix TechBlog - Medium
C
Cybersecurity and Infrastructure Security Agency CISA
V
Vulnerabilities – Threatpost
V
Visual Studio Blog
GbyAI
GbyAI
PCI Perspectives
PCI Perspectives
D
DataBreaches.Net
Jina AI
Jina AI
H
Heimdal Security Blog
云风的 BLOG
云风的 BLOG
P
Privacy International News Feed
A
About on SuperTechFans
J
Java Code Geeks
美团技术团队
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
News | PayPal Newsroom
有赞技术团队
有赞技术团队
MyScale Blog
MyScale Blog
博客园 - 司徒正美
C
Check Point Blog
T
Threat Research - Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
C
Cyber Attacks, Cyber Crime and Cyber Security
I
Intezer
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
Apple Machine Learning Research
Apple Machine Learning Research
Hugging Face - Blog
Hugging Face - Blog
The Last Watchdog
The Last Watchdog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
Cisco Talos Blog
Cisco Talos Blog
W
WeLiveSecurity
Hacker News: Ask HN
Hacker News: Ask HN
Recent Commits to openclaw:main
Recent Commits to openclaw:main
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
D
Docker
博客园 - Franky
Security Archives - TechRepublic
Security Archives - TechRepublic

小松鼠的博客

记录一次线上k8s工作节点无法创建容器的问题排查思路与解决办法 记一次线上GoLang项目OOM排查过程 从LastPass转向拥抱开源KeePass的心路历程 故障定位与 AI 结合前后端编码实践 FileBeat收集nginx-ingress-controller日志 K8s云原生环境下文件描述符占用过高查询思路 2024年最新关闭火绒安全工具的开机自启方法 Kubernetes任务调度实践-Go语言实现Job和CronJob对比分析 离线更新k8s环境下的trivy漏洞库方法 使用Go语言接入Choerodon实现基于OAuth2的统一身份认证登录 在Vue2中自定义Switch组件并实现父子组件双向数据绑定 关于docker jdk1.8镜像中的GB18030-2022标准支持及验证 Go框架gin中的session存储gin-contrib-sessions和go-session 关于修改node_module中的源码问题记录 docker-compose网络和内网服务IP冲突问题 慎用存储过程:一条语句引发的数据库存储100%占用 Spring Boot中4种文件下载方法的实现 避坑-不能将specific类型的gitlab-runner改变为share类型 Docker compose中的MySQL主从复制模式和percona-toolkit工具使用 在minio中开启https访问以及使用rclone备份minio桶 在多机Docker环境下部署Choerodon的解决方案 Prometheus中Monitor添加对SpringBoot Actuator的Basic认证 在Nginx的容器镜像中隐藏Nginx的Server响应头 K8s中的两种nginx-ingress-controller及其区别 两个docker工具:runlike和whaler Grafana中的邮件报警和截图插件grafana-image-enderer K8s中externalName-service和services-without-selectors maven配置文件settings.xml中的一些概念总结 K8s中flexvolume插件驱动的安装 K8s中的coredns无法解析svc问题排查 K8s中使用Ingress访问请求体过大问题解决 关于k8s中对于SpringBoot应用TCP类型的就绪探针不准确的问题发现 K8s中的环境变量与应用程序的对应关系与操作 SpringMVC4升级为SpringBoot2实战 在Vmware中Ubuntu22.04的vm-tools和网络问题 修改k8s节点主机名并重新加入集群 离线安装Grafana插件 Spring Data Jpa 中使用CriteriaBuilder动态拼接SQL 在SpringBoot项目配置Liquibase数据库版本管理 记录Vue中父子组件传值的实战应用 实现单例模式的8种方法 三种常用的生产者消费者模式实现 使用两个线程交替打印0-100的奇偶数 关于部署于JBoss5中的Spring应用获取项目真实部署路径的问题 获取下一个完全对称日 通过短信验证码验证修改密码的解决方案 在Win10中使用Win+R快速启动软件 使用RSA加解密时注意Cipher.getInstance(String var0,Provider var1)提供的Provider是否正确 在RestEasy2.x中解决接口重复提交问题 几道简单的CTF题目思路 重温Spring---Spring事务控制与基于XML和注解的配置方法 重温Spring---Spring AOP基于XML和注解的配置 重温Spring---AOP动态代理和Spring AOP及其基本原理 重温Spring---Spring IOC基于XML和注解的配置和比较 在Windows10中安装MySQL5.7 Zip版本及常用配置 重温Spring---使用Spring IOC解决程序耦合 策略模式与责任链模式实战应用 Linux上直接打开war包修改文件 在Windows上运行两个微信的简单脚本 ThreadPoolExecutor的使用方法与分页查询数据实例 IDEA中Shelve Changes 和 Git Stash 通过resteasy发布RESTful接口 解决前端请求后台接口,后台报错Can not deserialize instance of java.util.ArrayList out of START_OBJECT token 使用VBA脚本汇总Excel文档 使用Jenkins+GitLab实现自动部署vue项目 Kubernetes:使用hostPath挂载nginx集群的配置文件和html 彻底搞定VirtualBox虚拟机的网络设定 在Docker中安装MySQL5.7并开启远程访问(附授权和修改密码方式) 利用git命令和java文件流 获取自己改动过的文件 浅谈Spring定时任务的使用(Scheduled注解) 在Spring项目简单配置Flyway(V4.2版本)数据库版本管理 解决Spring单元测试中因外键关联导致的失败integrity constraint violation:foreign key no action Redis安装与哨兵模式配置入门 关于Vue中使用Element-UI样式row-class-name失效的问题 Windows系统查看端口占用、结束进程方法和命令 层次分析法(AHP)分析步骤与计算方法 源码分析之解决layui框架重载表格时额外参数不清空的问题 Spring Data Jpa 返回自定义对象(实体部分属性、多表联查) 如何将一个jar放到本地maven仓库中 关于SSM项目停止Tomcat时Log4j出现java.lang.NoClassDefFoundError: 获取el-table单元格值并根据该值对元素自定义样式渲染 解决Git每次push都要重新输入账号密码和HttpRequestException encountered的问题 解决前后端分离项目中Vue不带cookies的问题 SSM集成Shiro自定义权限过滤器不执行解决方案 SSM集成Shiro不进入自定义Realm的doGetAuthorizationInfo的解决方案 Vue+SSM中使用Token验证登录 Git拉代码推送代码提示密码错误如何修改 Git配置SSH Key(Git配置多个账户) 安装Tomcat服务器以及错误汇总(tomcat8.0、jdk8) 关于我
Element-UI中实现可动态增加行列和可编辑单元格的表格
ycyin · 2020-06-27 · via 小松鼠的博客

2020年6月27日大约 5 分钟前端技术VueAHPElement-UIel-table动态表格


前言

基本需求场景:使用层次分析法(AHP)时,需要前端实现一个可动态添加表格行列、且单元格可编辑的表格。关于层次分析法可查看另一篇博客:层次分析法(AHP)分析步骤与计算方法

使用到的技术主要是vueelement-uielement-ui官方文档:https://element.eleme.cn/#/zh-CN/component/tableel-table组件不支持动态增加列,增加行则可以通过增加数据行实现,并且并不支持单元格的编辑,唯一可用到的就是可以监听单元格的双击/单击事件。

实现效果

可访问CodePen在线查看代码和效果展示:https://codepen.io/yyc007/pen/abdyNeb

效果展示
效果展示

基本思路

动态增加行列: 动态增加行可以巧妙地改变数据的行数即可实现。而动态增加列只能自己写了,实现方式是将表格的列组件el-table-column使用v-for指令循环渲染,根据列的数量确定循环次数以此来确定表头。

表格重新渲染: 上面提到当表格的列数量变化时表头也会随着数量的变化而变化,这时需要为表格设置key值,并且在列数量变化时修改key值以保证表格每次都会重新渲染。(后来发现没必要这么做)。

每一个单元格能够有唯一的key值: 因为还需要实现单元格的编辑(单击单元格可编辑)和表格右上三角不可编辑两个功能,所以需要唯一地确定每一个单元格(需要确定是哪个单元格被点击、哪个单元格不可编辑/点击),而el-table组件的单击回调方法参数cell中的cellIndex无法唯一确定单元格,需要自定义一下每个单元格的索引值。同时,单元格编辑时的input也要随着单元格确定一个key值。

表格右上三角不可编辑: 每个单元格的唯一索引确定了,这个就好做了,只需要设置一下单元格样式,并且当点击右上三角的单元格(column.index > row.index)时不做任何反应即可。

代码实现

部分核心代码和讲解。完整代码和效果可访问上面的codepen查看。

  • 先来看看当表格的行列数量值发生改变时(动态增加行列)需要做些什么。从下面的代码中可以看出主要就是初始化数据和表头。
handlerSelectChange(value) { // value就是表格的行列数量
    let tempTableThead = []
    let tempTableData = []
    let tableObjData = {}
    // 生成初始行数据
    for (let i = 1; i <= value; i++) {
        tableObjData['item' + i] = 1
    }
    // 初始化第一列表头
    tempTableThead.push({
      key: 'item0',
      label: ''
    })
    // 动态添加行和列
    for (let i = 1; i <= value; i++) {
      let temp = {}
      //添加列[表头]
      tempTableThead.push({
        key: 'item' + i,
        label: '因素' + i
      })
      //为每一行的第一列添加不用的因素名(值)
      temp['item0'] = '因素' + i
      // 复制属性
      Object.assign(temp, tableObjData)
      //添加行
      tempTableData.push(temp)
    }
    this.tableData = tempTableData
    this.formThead = tempTableThead
}

HTML核心代码:

<el-table :key="key" :cell-class-name="tableCellClassName" :data="tableData" @cell-click="handleCellClick" :show-header="true" border :header-cell-style="tableHeadCellStyle" :cell-style="tableCellStyle">
    <el-table-column v-for="item in formThead" :key="item.key" :label="item.label">
       <template slot-scope="scope">
          <div :class="[inputClass]">
             <el-input ref="inputVal" size="small" @blur="handleInputBlur" v-model="scope.row[item.key]" :row-index=scope.$index @change="handleEdit($event,scope.row,scope.column)">
                </el-input>
           </div>
           <span :class="[spanClass]">{{ scope.row[item.key] }}</span>
        </template>
      </el-table-column>
</el-table>
  • 使用data 属性为表格提供数据,需要动态生成行时改变数据行数即可。

  • 使用header-cell-stylecell-style 分别为表格的表头和右上三角的所有单元格设置样式(背景色)。

// 表头单元格样式
tableHeadCellStyle({row,column,rowIndex,columnIndex}) {
   return 'background: #DCDCDC'
},
// 表格单元格样式
tableCellStyle({row,column,rowIndex,columnIndex}) {
   if (columnIndex > rowIndex) return 'background: #DCDCDC'
}
  • 使用v-for 标签生成表格的列el-table-column , 需要动态生成列时改变formThead (即存放表头的数组)即可。

  • 使用单元格的 className 的回调方法 cell-class-name 为每一个单元格设置唯一索引。

// 给行列索引赋值,为了在点击单元格时可以唯一确定单元格
tableCellClassName({row,column,rowIndex,columnIndex}) { //注意这里是解构
    //利用单元格的 className 的回调方法,给行列索引赋值
    row.index = rowIndex;
    column.index = columnIndex;
}
  • 每一个单元格中存放一个divspan 标签,默认显示span,通过动态改变它们的class来改变css样式控制它们显示还是隐藏。需要为input设置ref值,方便确定到底是哪一个input以获得input焦点。可以看出有多个ref值为inputVal的input,因为单元格有唯一索引,所以根据单元格的索引就可以确定是哪个input 当单击单元格时,隐藏span,显示input并获取焦点;当input失去焦点时显示span,隐藏input。使用cell-click 事件监听单元格的单击。

  • 使用cell-click 事件监听单元格点击,此时主要做的就是控制表格右上三角不可点击,同时需要显示input,并让input 获取焦点:

handleCellClick(row, column, cell, event) {
   // cell中的cellIndex无法唯一确定单元格,我们自己定义
   // const cellIndex = cell.cellIndex
   const cellIndex = (this.form.value + 1) * row.index + column.index
   // 不让点击表格右上三角(包括对角线,其中对角线column.index-1 = row.index)
   if (column.index > row.index) {
       return
   }
   //显示input,隐藏span
   cell.childNodes[0].firstChild.className = "box-item-block"
   cell.childNodes[0].lastChild.className = "box-item-none"
   // 获取input焦点
   this.$nextTick(() => {
      // 获取到对应的第cellIndex个ref并获取焦点  
      this.$refs.inputVal[cellIndex].$el.querySelector('input').focus()
   })
}
  • 在input框组件上使用blur事件监听失去焦点,此时隐藏input,显示span:
handleInputBlur(event) {
   const _event = event
   const ev = _event.target.offsetParent.offsetParent.childNodes[0]
   if (_event && _event.target && _event.target.offsetParent &&
       _event.target.offsetParent.offsetParent && ev.firstChild &&
       ev.lastChild) {
         const inputElement = ev.firstChild
          const spanElement = ev.lastChild
          // 隐藏input,显示span
          inputElement.className = "box-item-none"
          spanElement.className = "box-item-block"
    }
}

参考:

  1. Element-UI官方文档
  2. Element-UI可编辑表格的实现
  3. 获取elementUI Table单击的一个单元格的列和行