树状表格子节点移动 - 在Vue.js中实现上下移动子节点的表格功能

目录

功能介绍

示例

代码

视图部分

逻辑部分

完整代码


功能介绍

        本文介绍了如何在Vue.js框架下实现一个树状表格,其中支持选择子节点行的上下移动。通过这个功能,用户可以方便地改变子节点的顺序。代码示例和详细的实现步骤将展示如何使用Vue.js的相关特性和组件实现这个功能。通过本文的介绍,您可以轻松了解如何在您的Vue.js项目中应用这个功能,以满足您的特定需求。     

示例

代码

视图部分

        实现父节点选择的代码

        在上次选中父节点的代码基础上加上操作行,生成上下移动的按钮: 

      <el-table-column align="center"><template slot-scope="scope" v-if="!scope.row.children"><el-button v-show="!validateOperate(scope.row, 'up')" size="mini" icon="el-icon-top" plain@click="handleSort(scope.row, 'up')"></el-button><el-button v-show="!validateOperate(scope.row, 'down')" size="mini" icon="el-icon-bottom" plain@click="handleSort(scope.row, 'down')"></el-button></template></el-table-column>

        新增列定义,用于显示上移和下移按钮。<template> 标签中定义了使用 slot-scope 来访问作用域插槽,在这个作用域下,使用了两个 <el-button> 元素来展示上移和下移按钮。为了使第一行与最后一行只有下移或上移,这里通过绑定 v-show 来控制按钮的显示与隐藏,根据 validateOperate() 方法的返回值确定按钮是否可见。@click 侦听器则会触发 handleSort() 方法来完成所在行的移动。

逻辑部分

组件数据和选中父节点的代码相同,获取tableData后,如果没有index,则自己遍历加上该属性。

   

methods对象新增方法:

  • getParent(id) 方法用于获取拥有指定子行 id 的父级行,它通过遍历 this.tableData 数组来寻找子行所属的父行。
    getParent(id) {let result = [];this.tableData.some(item => {item.children.some(d => {if (d.id == id) result = item;})});return result;}
  • validateOperate(row, type) 方法用于根据指定的操作类型(上移或下移)检查当前行是否可进行该操作。首先判断是否最内层的子树,对于上移操作,当前行的索引为0时返回true,隐藏上移按钮;对于下移操作,当前行的索引等于自身所处children数组的长度减1时返回true,隐藏下移按钮。
    validateOperate(row, type) {if (!row.children) {if (type == 'up' && row.index == 0) {return true;}else if (type == 'down') {return this.getParent(row.id).children.length - 1 == row.index;}else {return false;}}}
  • handleSort(row, type) 方法用于处理行的上移和下移操作。它首先获取该行的父级行和父级行的 ID,并定义一个标志变量 downFlag。然后通过遍历 parent.children 数组来查找需要进行上移或下移操作的行,并进行相应的移动和调整索引的操作。最后,更新父级行的子行列表和相关数据。
    handleSort(row, type) {let parent = this.getParent(row.id);let parentId;let downFlag = true;this.tableData.forEach(item => {if (item.children === parent) parentId = item.id;});console.log(parent);parent.children.some(item => {if (type == 'up') {if (item.index == row.index - 1) {parent.children.splice(row.index, 1);parent.children.splice(item.index, 0, row);parent.children.forEach((child, index) => child.index = index);this.tableData.forEach(data => {if (data.id === parentId) data.children = parent.children;});}} else if (type == 'down' && downFlag) {if (item.index == row.index + 1) {parent.children.splice(row.index, 1);parent.children.splice(item.index, 0, row);parent.children.forEach((child, index) => child.index = index);this.tableData.forEach(data => {if (data.id === parentId) data.children = parent.children;});downFlag = false;}}})}

完整代码

<template><div><el-table v-loading="loading" :data="tableData" style="width: 100%;margin: 20px;" row-key="id" borderdefault-expand-all :tree-props="{ children: 'children' }"><el-table-column width="60" align="center"><template slot="header" slot-scope="scope"><el-checkbox :indeterminate="isIndeterminate" v-model="isFullChecked" @change="checkAllChange"></el-checkbox></template><template slot-scope="{row}" v-if="row.children"><el-checkbox :indeterminate="row.isIndeterminate" :value="row.checked" @change="checkRowChange(row)"></el-checkbox></template></el-table-column><el-table-column prop="series" label="系列" align="center"></el-table-column><el-table-column prop="num" label="编号" align="center"></el-table-column><el-table-column prop="name" label="名字" align="center"></el-table-column><el-table-column align="center"><template slot-scope="scope" v-if="!scope.row.children"><el-button v-show="!validateOperate(scope.row, 'up')" size="mini" icon="el-icon-top" plain@click="handleSort(scope.row, 'up')"></el-button><el-button v-show="!validateOperate(scope.row, 'down')" size="mini" icon="el-icon-bottom" plain@click="handleSort(scope.row, 'down')"></el-button></template></el-table-column></el-table></div>
</template><script>
export default {data() {return {isFullChecked: false,isIndeterminate: false,loading: true,tableData: []}},mounted() {this.getList()},watch: {tableData() {this.isFullChecked = false;this.isIndeterminate = false;}},methods: {getList() {const tableData = [{id: 1,series: 'DDLC',children: [{id: 11,num: '1',name: 'monika',index: 0,},{id: 12,num: '2',name: 'nasuki',index: 1,},{id: 13,num: '3',name: 'sayori',index: 2,},{id: 14,num: '4',name: 'yuri',index: 3,}]},{id: 2,series: 'Bloom Into You',children: [{id: 21,num: '11',name: 'nanami',index: 0,},{id: 22,num: '12',name: 'yuu',index: 1,}]},];tableData.forEach(item => {item.checked = false;item.isIndeterminate = false;})this.tableData = tableData;this.total = this.tableData.length;this.loading = false;},checkAllChange() {const recursionSetChecked = (item, checked) => {item.checked = checked;item.isIndeterminate = false;}this.isIndeterminate = false;this.tableData.forEach(item => recursionSetChecked(item, this.isFullChecked));},checkRowChange(data) {data.checked = !data.checked;const recursion = node => {if (node.children && node.children.length > 0)node.isIndeterminate = false;return node;};this.tableData.forEach(item => recursion(item));if (this.tableData.every(item => item.checked)) {this.isFullChecked = true;}else if (this.tableData.every(item => !item.checked)) {this.isFullChecked = false;}this.isIndeterminate = this.tableData.some(item => item.isIndeterminate)? true: this.tableData.some(item => !item.checked) && this.tableData.some(item => item.checked);},getParent(id) {let result = [];this.tableData.some(item => {item.children.some(d => {if (d.id == id) result = item;})});return result;},validateOperate(row, type) {if (!row.children) {if (type == 'up' && row.index == 0) {return true;}else if (type == 'down') {return this.getParent(row.id).children.length - 1 == row.index;}else {return false;}}},handleSort(row, type) {let parent = this.getParent(row.id);let parentId;let downFlag = true;this.tableData.forEach(item => {if (item.children === parent) parentId = item.id;});console.log(parent);parent.children.some(item => {if (type == 'up') {if (item.index == row.index - 1) {parent.children.splice(row.index, 1);parent.children.splice(item.index, 0, row);parent.children.forEach((child, index) => child.index = index);this.tableData.forEach(data => {if (data.id === parentId) data.children = parent.children;});}} else if (type == 'down' && downFlag) {if (item.index == row.index + 1) {parent.children.splice(row.index, 1);parent.children.splice(item.index, 0, row);parent.children.forEach((child, index) => child.index = index);this.tableData.forEach(data => {if (data.id === parentId) data.children = parent.children;});downFlag = false;}}})}}
}
</script>

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端demo】CSS border-radius可视化 原生实现

文章目录 效果原理代码 前端demo系列目录&#xff1a;https://blog.csdn.net/karshey/article/details/132585901 效果 效果预览&#xff1a;https://codepen.io/karshey/pen/zYyBPBR 参考&#xff1a; Fancy Border Radius Generator (9elements.github.io) https://borde…

《2023年网信人才培训-网络安全从业人员能力素养提升培训》第一期成功举办

随着网络强国和数字中国建设的步伐加快&#xff0c;建设规模宏大、结构合理、素质优良的人才队伍成为一项重要工作。知了汇智作为数字产教融合基地&#xff0c;通过与高校、企业等多方合作&#xff0c;建立了完整的网络安全人才培养生态链。凭借自身技术优势和丰富的产业资源&a…

【小沐学Unity3d】3ds Max 骨骼动画制作(CAT、Character Studio、Biped、骨骼对象)

文章目录 1、简介2、 CAT2.1 加载 CATRig 预设库2.2 从头开始创建 CATRig 3、character studio3.1 基本描述3.2 Biped3.3 Physique 4、骨骼系统4.1 创建方法4.2 简单示例 结语 1、简介 官网地址&#xff1a; https://help.autodesk.com/view/3DSMAX/2018/CHS https://help.aut…

程序开发:构建功能强大的应用的艺术

程序开发是在今天的数字化时代中扮演重要角色的一项技术。通过编写代码&#xff0c;开发人员能创造出无数不同的应用&#xff0c;从简单的计算器到复杂的社交平台。电子商务应用、在线教育平台、医疗记录系统等&#xff0c;都重视程序开发的重要性&#xff0c;通过这其中的交互…

docker 笔记1

目录 1.为什么有docker ? 2.Docker 的核心概念 3.容器与虚拟机比较 3.1传统的虚拟化技术 3.2容器技术 3.3Docker容器的有什么作用&#xff1f; 3.4应用案例 4. docker 安装下载 4.1CentOS Docker 安装 4.2 Docker的基本组成 &#xff1f;&#xff08;面试&#xff09…

linux系统中串口驱动框架基本分析(经典)

第一&#xff1a;区分不同的终端类型 串行端口终端&#xff08;/dev/ttySn&#xff09; 串行端口终端&#xff08;Serial Port Terminal&#xff09;是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。 有段时间这些串行端口设备通常被称为终…

sql:SQL优化知识点记录(九)

&#xff08;1&#xff09;小表驱动大表 对sql调优的分析&#xff1a; 排序优化&#xff1a; 数据库的连接方式&#xff0c;里面的数据尽量这样连接&#xff0c;尽量选择第一个方式&#xff0c;因为两个表的连接一共建立5次连接&#xff0c;第二个建立1000次连接&#xff0c;从…

python 之import与from import 导入库的解析与差异

文章目录 1. **使用import导入整个模块**&#xff1a;2. **使用from import导入特定内容**&#xff1a;注意事项别名的使用 在Python中&#xff0c;import和from import是用于导入模块中内容的两种不同方式。下面详细介绍它们的用法和差异&#xff1a; 1. 使用import导入整个模…

从零开始探索C语言(四)----循环

文章目录 1. C 循环1.1 while 循环1.2 for 循环1.3 do...1.4 嵌套循环 2. 循环控制语句2.1 break 语句2.2 continue 语句2.3 goto 语句 1. C 循环 有的时候&#xff0c;我们可能需要多次执行同一块代码。一般情况下&#xff0c;语句是按顺序执行的&#xff1a;函数中的第一个语…

路由器的简单概述(详细理解+实例精讲)

系列文章目录 华为数通学习&#xff08;4&#xff09; 目录 系列文章目录 华为数通学习&#xff08;4&#xff09; 前言 一&#xff0c;网段间通信 二&#xff0c;路由器的基本特点 三&#xff0c;路由信息介绍 四&#xff0c;路由表 五&#xff0c;路由表的来源有哪些…

bazel构建原理

调度模型 传统构建系统有很多是基于任务的&#xff0c;例如 Ant&#xff0c;Maven&#xff0c;Gradle。用户可以自定义"任务"(Task&#xff09;&#xff0c;例如执行一段 shell 脚本。用户配置它们的依赖关系&#xff0c;构建系统则按照顺序调度。 基于 Task 的调度…

计算机网络 概述部分

目录 计算机网络在信息时代的作用 计算机网络的重要特征 网络&#xff0c;internet,Internet的区别 局域网 广域网的区别 网络协议的分层 计算机网络在信息时代的作用 计算机网络的重要特征 连通性&#xff1a;彼此联通&#xff0c;交换信息 共享性&#xff1a;信息共享…