首页 > 编程知识 正文

如何实现el-tree 父子节点左右布局

时间:2023-11-21 20:00:12 阅读:289778 作者:HHLQ

本文将从多个方面全面阐述el-tree 父子节点左右布局的实现方式。

一、布局样式的实现

在实现el-tree 父子节点左右布局时,我们需要完成的第一步是布局样式的实现。我们可以通过CSS的flex布局实现这一目标。下面是示例代码:

<style>
  .tree-wrapper {
    display: flex;
  }
  
  .tree-parent {
    flex: 1;
  }
  
  .tree-child {
    flex: 2;
  }
</style>

在代码中,我们设置了一个名为tree-wrapper 的元素,通过flex布局实现其内部的tree-parent 和tree-child 的左右布局。具体实现方式是tree-parent 的flex值为1,tree-child 的flex值为2,这样就可以实现tree-child 是tree-parent 的两倍宽度了。

二、树形结构数据的处理

在el-tree 父子节点左右布局的实现中,要想让左侧的tree-parent 和右侧的tree-child 已树形结构的方式呈现,我们需要对数据进行处理。具体步骤如下:

1、讲树形结构的数据转化为扁平结构

function flattenData(data) {
  let res = []
  data.forEach(item => {
    res.push(item)
    if (item.children && item.children.length > 0) {
      res = res.concat(flattenData(item.children))
    }
  })
  return res
}

2、利用递归函数将扁平结构的数据转换为左侧tree-parent 和右侧tree-child 对应的数据格式

function transferData(data) {
  let res = []
  let index = 0
  const dfs = (node) => {
    const localIndex = ++index
    res.push({
      ...node,
      index: localIndex
    })
    if (node.children && node.children.length > 0) {
      node.children.forEach(child => {
        dfs(child)
      })
      res.push({
        isPlaceholder: true,
        parentIndex: localIndex
      })
    }
  }
  data.forEach(node => {
    dfs(node)
  })
  return res
}

在上述代码中,我们首先定义了一个 flattenData 函数,用于将树形结构的数据转换为扁平结构的数据。然后,我们定义了一个递归函数 dfs,该函数用于遍历扁平结构的数据并转换为左侧tree-parent 和右侧tree-child 对应的数据格式。其中,我们通过isPlaceholder 属性标记出tree-parent 和tree-child 中的占位符,以保证布局时左右两个部分元素的位置对应正确。

三、el-tree 渲染

在数据处理完成后,我们需要将数据渲染成el-tree左右布局的形式。下面是一个完整的实现示例:

<template>
  <div class="tree-wrapper">
    <el-tree
      :data="parentData"
      :props="treeProps"
      node-key="index"
      class="tree-parent"
      @node-click="handleNodeClick">
      <span class="custom-tree-node" slot-scope="{ node, data }">
        {{ data.label }}
      </span>
    </el-tree>
    <el-tree
      :data="childData"
      :props="treeProps"
      node-key="index"
      class="tree-child"
      @node-click="handleNodeClick">
      <template slot-scope="{ node, data }">
        <span v-if="data.isPlaceholder" class="tree-placeholder"></span>
        <span v-else class="custom-tree-node">
          {{ data.label }}
        </span>
      </template>
    </el-tree>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        treeData: [
          {
            label: '一级 1',
            children: [
              {
                label: '二级 1-1',
                children: [
                  {
                    label: '三级 1-1-1'
                  },
                  {
                    label: '三级 1-1-2'
                  }
                ]
              },
              {
                label: '二级 1-2',
                children: [
                  {
                    label: '三级 1-2-1'
                  },
                  {
                    label: '三级 1-2-2'
                  }
                ]
              }
            ]
          },
          {
            label: '一级 2',
            children: [
              {
                label: '二级 2-1',
                children: [
                  {
                    label: '三级 2-1-1'
                  },
                  {
                    label: '三级 2-1-2'
                  }
                ]
              },
              {
                label: '二级 2-2',
                children: [
                  {
                    label: '三级 2-2-1'
                  },
                  {
                    label: '三级 2-2-2'
                  }
                ]
              }
            ]
          }
        ]
      }
    },
    computed: {
      parentData() {
        return this.transferData(this.treeData).filter(item => !item.isPlaceholder)
      },
      childData() {
        return this.transferData(this.treeData).filter(item => item.isPlaceholder)
      },
      treeProps() {
        return {
          label: 'label',
          children: 'children'
        }
      }
    },
    methods: {
      handleNodeClick(data) {
        console.log(data)
      },
      flattenData(data) {
        let res = []
        data.forEach(item => {
          res.push(item)
          if (item.children && item.children.length > 0) {
            res = res.concat(this.flattenData(item.children))
          }
        })
        return res
      },
      transferData(data) {
        let res = []
        let index = 0
        const dfs = (node) => {
          const localIndex = ++index
          res.push({
            ...node,
            index: localIndex
          })
          if (node.children && node.children.length > 0) {
            node.children.forEach(child => {
              dfs(child)
            })
            res.push({
              isPlaceholder: true,
              parentIndex: localIndex
            })
          }
        }
        data.forEach(node => {
          dfs(node)
        })
        return res
      }
    }
  }
</script>

在上面的代码中,我们通过计算属性 parentData 和childData 分别为左侧tree-parent 和右侧tree-child 绑定数据,实现其左右布局;通过treeProps 定义el-tree 的props属性;通过handleNodeClick 监听节点点击事件。同时,我们在template标签中为tree-parent 和tree-child 的每一个节点绑定了文本显示方式,并对tree-child 中的占位元素进行了处理,以保证页面正常显示。

四、注意事项

在开发过程中,需要注意以下事项:

1、由于el-tree 组件需要传入的data 数据必须是一个符合某种格式的树形结构数据,为了实现左右布局不得不对该数据结构进行一定的额外处理;

2、在处理数据结构时,需要特别处理tree-子节点。特别是在tree-child 上,为了保证一些内容的展示,还需要添加一些需要主动添加的自定义节点,如上述代码中的 isPlaceholder。

总结

本文对el-tree 父子节点左右布局进行了全面深入地阐述。无论是实现布局样式、数据处理,还是对el-tree 的渲染,都有详细的介绍和代码示例。相信通过本文的学习,读者对于el-tree 父子节点左右布局的实现方式已经有了更深入的认识,希望本文能够对您有所帮助。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。