tree组件实现折叠与展开功能(方式1 - expandedTree计算属性)

本示例节选自vue3最新开源组件实战教程大纲(持续更新中)的tree组件开发部分。考察响应式对象列表封装和computed计算属性的使用,以及数组reduce方法实现结构化树拍平处理的核心逻辑。

实现思路

第一种方式:每次折叠或展开后触发扁平化列表的重新计算和渲染。

第二种方式:每次折叠或展开后出发其所有子节点的visible计算属性重新计算,用v-if进行动态渲染。

这里我们先讨论第一种方案的实现。

实现方式

在循环遍历树节点时,增加要渲染的内容:

<div class='juan-tree-node' key=... style=...>
  {/* 渲染节点前的内容,父节点需要展示隐藏或展开按钮,叶子节点留出空的span来占据位置 */}
  {node.isLeaf ? (
    <span class='mr-1 inline-block w-[20px]'></span>
  ) : (
    <button onClick={() => toggleNode(node)} class='mr-1 inline-block h-[18px] w-[20px]'>
      {node.expanded ? <span>-</span> : <span>+</span>}
    </button>
  )}
  {node[labelName as 'label']}
</div>

节点的展开与折叠操作,注意需要操作响应式的对象,这样会触发计算属性的重新计算:

// 将树拍平的扁平化列表结构,包装成响应式列表,操作一个节点的展开与折叠,其实操作的是响应式列表中的一个元素,以便触发expandedTree计算属性重新计算。
const flatData = ref(generateFlatTree(data, optionProps))
const toggleNode = (node: IFlatTreeNode) => {
  // 注意,这里操作的其实是响应式列表中的一个元素,改变其属性会触发expandedTree重新计算
  node.expanded = !node.expanded
}
// 该计算属性用于计算已经展开的所有节点,包括手动设置expanded属性为false的父节点,而排除掉扁平化列表中折叠节点的所有子孙节点。
const expandedTree = computed(() => {
  const result = []
  for (let i = 0; i < flatData.value.length; i++) {
    const item = flatData.value[i]
    // 如果是父节点并且非展开(默认是折叠的)则跳过其所有子孙节点。
    if (!item.isLeaf && item.expanded !== true) {
      // 跳过内部所有节点
      i += item.length!
    }
    result.push(item)
  }
  return result
})

不要忘了,tree模板中遍历的对象为expandedTree.value

跳过多少个需要隐藏的子节点列表呢?

这是expandedTree计算属性实现中的关键点,咱们的实现是给IFlatTreeNode上加一个length属性,

// 扩展的扁平化节点
export interface IFlatTreeNode extends ITreeNode {
  ...
  length?: number // 设置其子孙节点的长度
}

该属性值是在generateFlatTree拍平函数中设置的:

在这里插入图片描述
执行效果:
在这里插入图片描述

存在的问题

存在的问题

  1. expandedTree计算属性每次都要整体进行计算,且对变化的部分做重新渲染
  2. IFlatTreeNodelength属性是在拍平函数中设置死的,append节点后,这个属性值应该是变化的。

下一小节,我们讲采用第二种实现方式来规避这个问题。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的代码,可以看出这是一个使用antd-v的table tree组件。要实现全部展开和全部折叠功能,可以通过控制每一行的展开状态来实现。 首先,你可以在data中添加一个属性来表示每一行的展开状态,例如isExpanded。然后,在expandIcon方法中,根据isExpanded的值来确定展开图标的类型。 要实现全部展开功能,你可以遍历data数组,将每一行的isExpanded属性设置为true。要实现全部折叠功能,你可以将每一行的isExpanded属性设置为false。 最后,重新渲染table组件,根据每一行的isExpanded属性来确定展开图标的类型。 以下是一个示例代码,用于实现全部展开和全部折叠功能: ```javascript // 在data中添加isExpanded属性 data.forEach(item => { item.isExpanded = true; // 默认全部展开 }); // 在expandIcon方法中根据isExpanded属性确定展开图标的类型 expandIcon(props) { if (props.record.children.length > 0) { if (props.record.isExpanded) { return ( <span class="table-icon" onClick={(e) => { props.onExpand(props.record, e); }}> <a-icon type="caret-down" /> </span> ); } else { return ( <span class="table-icon" onClick={(e) => { props.onExpand(props.record, e); }}> <a-icon type="caret-right" /> </span> ); } } else { return <span style="margin-right:19px"></span>; } } // 添加全部展开和全部折叠功能 handleExpandAll() { data.forEach(item => { item.isExpanded = true; }); // 重新渲染table组件 // ... } handleCollapseAll() { data.forEach(item => { item.isExpanded = false; }); // 重新渲染table组件 // ... } ``` 通过调用handleExpandAll和handleCollapseAll方法,你可以实现全部展开和全部折叠功能。 #### 引用[.reference_title] - *1* [antd-vue的树形table组件修改展开图标](https://blog.csdn.net/qq_40567849/article/details/124443188)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java小卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值