Vue3可媲美Element Plus Tree组件开发之append节点

在前面的章节,我们完成了可媲美Element Plus Tree组件的基本开发。通过实现各种计算属性,tree数据状态变化引起的视图更新被计算属性所接管了,无需我们再手动做各种遍历、查找以及手动监听操作,这样后续开发高级功能变得易如反掌啦!!

在这里插入图片描述

看下提供给用户的vitepress文档说明:

在这里插入图片描述

在这里插入图片描述

操作演示:

在这里插入图片描述

前面我们实现了几个计算属性:

  • index

    节点在扁平化列表中的位置索引

  • length

    父节点的所有子孙节点的长度

  • visibleLength

    可见子孙节点的长度

  • lineLength

    参照线的长度

这些计算属性在新增一个节点,尤其是子节点时都会被影响到,触发重新计算以保证前面实现的基本功能是完好的。而无需我们在实现新增节点时再去兼顾基础功能,这就是Vue3 composition api的计算属性的魅力,让复杂的功能变得简单,组件的开发者只需要把关注点放到影响计算属性变化的数据上即可,Life is so easy!

新增类型、接口

定义ts的类型和接口,注意给用户提供的接口一定要遵循“迪米特法则”。

在这里插入图片描述

核心插入逻辑

/*** 新增顶级节点* @param child 要新增的叶子节点* @param data 扁平化节点列表* @param treeData 结构化节点树* @param optionProps 组件配置选项*/
export function appendTop(child: ILeafNode, data: IFlatTreeNode[], treeData: ITreeNode[], optionProps: OptionProps) {// 节点id命名逻辑:如果指定了就用用户指定的,否则按照列表长度生成child.id = child.id || 'id-' + (data.length + 1)// 从新增节点拷贝数据作为original child nodeconst ocNode = { ...child }// 扁平化new child nodeconst ncNode = {...child,level: 1,isLeaf: true,originalNode: ocNode} as IFlatTreeNode// 要插入的位置为列表最后const insertIndex = data.length// 绑定新插入的扁平化节点的前置节点ncNode.prev = data[data.length - 1]// 对新的扁平化节点进行初始化initFlatTreeNode(ncNode, optionProps)// 原始树结构中新增节点,注意!!操作的是响应式数据ref(treeData).value.push(ocNode as never)// 扁平化列表中插入新节点ref(data).value.splice(insertIndex, 0, ncNode as never)
}function initFlatTreeNode(node: IFlatTreeNode, optionProps: OptionProps) {.../*** 给扁平化节点绑定新增子节点的方法* @param child 新增的子节点* @param data 扁平化列表*/node.append = (child: ILeafNode, data: IFlatTreeNode[]) => {// 同新增一级节点child.id = child.id || 'id-' + (data.length + 1)// 当前节点原始节点const oNode = node.originalNode// 新增节点原始节点const ocNode = { ...child }// 新增节点扁平化节点const ncNode = {...child,parent: node, // 绑定父节点level: node.level + 1,isLeaf: true,originalNode: ocNode} as IFlatTreeNode// 计算插入位置const insertIndex = calcInsertIndex(node)// 插入到最后的情况下,设置前置节点if (insertIndex === data.length) {ncNode.prev = data[data.length - 1]} else {// 插入到中间,绑定prev的逻辑,把prev链接起来const next = data[insertIndex]ncNode.prev = next.prev// 注意操作的是响应式对象,以确保可以触发index属性重新计算!!ref(next).value.prev = ncNode as never}// 初始化扁平化节点initFlatTreeNode(ncNode, optionProps)// 通过响应式对象获取其操作对象const oNodeVal = ref(oNode).valueconst nodeVal = ref(node).valueconst childrenName = optionProps.childrenName as 'children'// 对原先的叶子节点进行设置和初始化,变为非叶子节点if (!oNodeVal[childrenName]) {oNodeVal[childrenName] = []initParentNode(oNode, optionProps)nodeVal.isLeaf = false}// 插入到原始结构化节点oNodeVal[childrenName].push(ocNode as never)// 所在的节点将其展开(如果折叠的话)oNodeVal.expanded = truenodeVal.expanded = true// 插入到扁平化节点列表ref(data).value.splice(insertIndex, 0, ncNode as never)}
}/*** 插入子节点位置逻辑:如果是叶节点,则为下一个位置,否则要加上子一代节点的长度* @param node*/
function calcInsertIndex(node: IFlatTreeNode): number {return node.index.value + 1 + (node.isLeaf ? 0 : node.originalNode.length!.value)
}

Tree组件模板调整

原先给icon插槽传入的节点参数,不符合迪米特法则,暴露了内部操作属性和方法,规范的做法是拷贝一个副本!!只给用户提供其关心的几个属性,调整为:

在这里插入图片描述

对于一级节点新增操作,我们将对tree组件expose一个可操作的对象,为此把这个对象中要定义的方法抽取到ts接口中,以方便客户端API的使用:

// Tree组件对外导出的方法定义
export interface ExposeProps {appendTop: (newNode: ILeafNode) => void
}

导出逻辑:

在这里插入图片描述

而针对节点的操作,给用户提供的API,包装一个函数来返回要操作的接口:

// 返回节点操作方法的函数
const nodeOperation = (node: IFlatTreeNode): ITreeNodeOperation => {// 注意,这里不应该直接给用户提供node,而是要包成对外公开的ITreeNodeOperation,遵循迪米特法则!!return {append(newNode: ILeafNode) {node.append(newNode, originalFlatData)}}
}

对应的插槽实现的地方:

在这里插入图片描述

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

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

相关文章

kafka架构+原理+源码

1.安装jdk17 sudo yum -y update sudo wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm sudo yum -y install ./jdk-17_linux-x64_bin.rpm、 sudo java -version 2.安装kafka How to easily install kafka without zookeeper | Aditya’s Blog …

好用的资产管理系统 国内5款资产管理系统排名

选择合适的固定资产管理系统对于企业的资产跟踪和维护至关重要。市场上有许多优秀的资产管理系统,每款系统都有其独特的功能和优势。本文将盘点5个好用的固定资产管理系统排名不分先后,帮助您了解它们的主要特点和适用场景,从而选择最适合您企…

【Java 数据结构】ArrayList类介绍

ArrayList类介绍 初识List接口ArrayList类ArrayList类是什么顺序表的模拟实现初始化增加元素删除元素查找元素修改元素 ArrayList类使用构造方法ArrayList源码阅读常用方法及其注意事项 初识List接口 List 是集合框架中的一个接口, 它的里面包含了一些方法, 例如add(), remove…

JAVA项目样本

学生管理系统SISM-v2.0 项目构建 ebtity 学生类:属性,setter,getter,toString(),构造器… dao层 数据交互,数组CRUD(增删改查) 接口 实现

《Techporters架构搭建》-Day03 功能权限设计

功能权限设计 引言权限介绍什么是权限权限的作用 RBAC概述RBAC的组成RBAC支持的安全原则RBAC模型 基于RBAC的权限设计用户管理角色管理菜单管理部门管理岗位管理 权限系统设计ER图标准RBAC模型表复杂RBAC模型表 多租户架构什么是多租户?多租户特点多租户模型竖井隔离…

汽车免拆诊断案例 | 2014 款上汽名爵 GT 车发动机无法起动

故障现象 一辆2014款上汽名爵GT车,搭载15S4G发动机,累计行驶里程约为18.4万km。该车因左前部发生碰撞事故进厂维修,更换损坏的部件后起动发动机,起动机运转有力,但无着机迹象。用故障检测仪检测,发现无法与…

(leetcode学习)236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖…

【BUG】已解决:TypeError: the JSON object must be str, bytes or bytearray, not dict

已解决:TypeError: the JSON object must be str, bytes or bytearray, not dict 目录 已解决:TypeError: the JSON object must be str, bytes or bytearray, not dict 【常见模块错误】 错误原因: 解决方案: 欢迎来到英杰社区…

2024最新手机软件APP下载排行网站源码 软件下载站PHP源码

源码介绍 这是一款简洁蓝色的手机软件下载应用排行、平台和最新发布网站源码,主要包括主页、APP列表页、APP详情介绍页、新闻资讯列表、新闻详情页、关于我们等模块页面。 软件下载站PHP网站源码,简单的部署上线,访问首页安装程序&#xff…

探索PyMuPDF:Python中的强大PDF处理库

探索PyMuPDF:Python中的强大PDF处理库 背景:为何选择PyMuPDF 在数字化时代,PDF文件因其跨平台的兼容性和对格式的严格保持而成为文档交换的通用格式。然而,处理PDF文件往往需要专门的工具或库。这就是PyMuPDF库的用武之地。PyMuP…

飞书群聊机器人自定义机器人接入,并实现艾特@群成员功能

飞书群聊机器人还是比钉钉的要麻烦一点,钉钉的直接通过手机号就可以艾特群里面的人,但是飞书的要想艾特群里面的人,需要使用用户的 Open ID 或 User ID。这两个ID怎么获取呢?还需要在飞书的开放平台上创建一个应用,然后…

【MySQL是怎样运行的 | 第二篇】MySQL三大日志文件

文章目录 2.MySQL三大日志文件2.1日志文件列表2.1.1 redo log2.1.2 bin log2.1.3 undo log 2.2redo log日志详讲2.3 binglog和redo log有什么区别?2.4一条更新语句的执行过程 2.MySQL三大日志文件 2.1日志文件列表 redo log:重做日志,记录了…

mysql面试(五)

前言 本章节从数据页的具体结构,分析到如何生成索引,如何构成B树的索引结构。 以及什么是聚簇索引,什么是联合索引 InnoDB数据结构 行数据 我看各种文档中有好多记录数据结构的,但是这些都是看完就忘的东西。在这里详细讲也没…

深度学习复盘与论文复现E

文章目录 一、项目复现的问题及其解决方案1、 Cannot find DGL C graphbolt library2、 “is“ with a literal. Did you mean ““?”3、运行SEG、SPG查看GATNet的网络结构4、关于LI-FPN项目找不到数据粒度不匹配问题5、关于LI-FPN项目num_samples为空6、解决路径问题7、 !ss…

Fork软件笔记:一键拉取仓库所有模块

Fork是一个好用的git工具,只是没有中文而已(不过不用翻译也能看使用)。 工具下载地址:https://fork.dev/ 界面展示: 当项目中仓库模块比较多时,可以看到每个模块都是一个分页,每一个都要手动切换…

Git 分布式版本控制系统、创建分支,跳转分支、git拉取、在码云上创建项目,进行pull 和 push、克隆码云上任意项目

目录 1.Git 分布式版本控制系统: 1.安装git 2.创建目录,进行初始化 3.写入Java文件,提交文件 4.文件放入仓库 2.创建分支,跳转分支(所有的git操作都应该工作在,指定的init 目录下进行) 1.…

【前端学习笔记】CSS基础一

一、什么是CSS 1.CSS 介绍 CSS(Cascading Style Sheets,层叠样式表)是一种用来控制网页布局和设计外观的样式语言。它使得开发者可以分离网页的内容(HTML)和表现形式(样式),提高了…

微信小程序:vant-weapp 组件库、css 变量

vant-weapp 组件库 前往 vant-weapp 官网 npm 使用限制:不支持依赖于 Node.js 内置库、浏览器内置对象、C 插件 的包。 安装 vant-weapp # 通过 npm 安装 npm i vant/weapp -S --production# 通过 yarn 安装 yarn add vant/weapp --production# 安装 0.x 版本 npm i…

学术研讨 | 区块链与隐私计算领域专用硬件研讨会顺利召开

学术研讨 近日,国家区块链技术创新中心主办,长安链开源社区支持的“区块链与隐私计算领域专用硬件研讨会”顺利召开,会议围绕基于区块链与隐私计算的生成式AI上链、硬件加速、软硬协同等主题展开讨论,来自复旦大学、清华大学、北京…

钉钉 ai卡片 stream模式联调

sdk连接 新建卡片模板下载node.js sdkconfig.json 配置应用信息 启动项目npm i npm run build npm run start连接成功 获取卡片回调 注册卡片回调事件调用https://api.dingtalk.com/v1.0/card/instances 创建卡片实例,返回实例Id //参数结构 {"cardTempla…