树形表格示例

树形表格完整示例(Vue 2 + Element UI)

功能包含:

  • 展示父子层级结构

  • 支持展开/收起子项

  • 操作列(编辑、删除)

  • 自定义状态标签

示例代码

复制代码
<template>
  <div class="tree-table-demo">
    <el-card>
      <el-table
        :data="menuTree"
        row-key="id"
        border
        style="width: 100%"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      >
        <el-table-column prop="title" label="标题" />
        <el-table-column prop="type" label="类型" />
        <el-table-column prop="path" label="访问路径" />
        <el-table-column prop="route" label="路由地址" />
        <el-table-column prop="component" label="页面组件" />
        <el-table-column prop="status" label="状态">
          <template slot-scope="scope">
            <el-tag type="success">{{ scope.row.status }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180">
          <template slot-scope="scope">
            <el-button type="text" size="small">编辑</el-button>
            <el-button type="text" size="small">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script>
export default {
  name: 'TreeTableDemo',
  data() {
    return {
      menuTree: [
        {
          id: 1,
          title: '系统管理',
          type: '目录',
          path: '/system',
          route: '/system',
          component: '',
          status: '已注册',
          children: [
            {
              id: 2,
              title: '菜单管理',
              type: '菜单',
              path: '/system/menu',
              route: '/system/menu',
              component: 'SystemMenuList',
              status: '已注册',
              children: [
                {
                  id: 3,
                  title: '新增',
                  type: '按钮',
                  path: 'SystemMenuCreate',
                  route: 'SystemMenuCreate',
                  component: '',
                  status: '已注册'
                },
                {
                  id: 4,
                  title: '修改',
                  type: '按钮',
                  path: 'SystemMenuUpdate',
                  route: 'SystemMenuUpdate',
                  component: '',
                  status: '已注册'
                },
                {
                  id: 5,
                  title: '删除',
                  type: '按钮',
                  path: 'SystemMenuDelete',
                  route: 'SystemMenuDelete',
                  component: '',
                  status: '已注册'
                }
              ]
            },
            {
              id: 6,
              title: '角色管理',
              type: '菜单',
              path: '/system/role',
              route: '/system/role',
              component: '',
              status: '已注册'
            },
            {
              id: 7,
              title: '用户管理',
              type: '菜单',
              path: '/system/user',
              route: '/system/user',
              component: '',
              status: '已注册'
            }
          ]
        },
        {
          id: 8,
          title: '工作台',
          type: '页面',
          path: '/workspace',
          route: '/dashboard/workspace/index',
          component: '',
          status: '已注册'
        },
        {
          id: 9,
          title: '关于',
          type: '菜单',
          path: '/about',
          route: '/core/about/index',
          component: '',
          status: '已注册'
        }
      ]
    }
  }
}
</script>

<style scoped>
.tree-table-demo {
  padding: 20px;
}
</style>

补充说明

属性 说明
row-key="id" 必须设置唯一标识字段,用于识别每一行
tree-props 指定子节点字段名(如 children)和是否有子节点的标志(可选)
嵌套结构 数据结构中通过 children 字段嵌套子项
操作列 可自定义按钮、图标、弹窗等交互

树形表格完整示例(Vue 2)

示例代码

复制代码
<template>
  <div class="tree-table">
    <table>
      <thead>
        <tr>
          <th>标题</th>
          <th>类型</th>
          <th>访问路径</th>
          <th>路由地址</th>
          <th>页面组件</th>
          <th>状态</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="row in flatData" :key="row.id" v-show="isVisible(row)">
          <td :class="'indent-' + row.level">
            <span
              v-if="Array.isArray(row.children) && row.children.length"
              class="toggle"
              @click="toggle(row)"
            >
              {{ row.expanded ? '▼' : '▶' }}
            </span>
            {{ row.title }}
          </td>
          <td>{{ row.type }}</td>
          <td>{{ row.path }}</td>
          <td>{{ row.route }}</td>
          <td>{{ row.component }}</td>
          <td>
            <span :class="['tag', row.status === '已注册' ? 'success' : 'info']">
              {{ row.status }}
            </span>
          </td>
          <td>
            <button class="btn" @click="edit(row)">编辑</button>
            <button class="btn" @click="remove(row)">删除</button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  name: 'TreeTable',
  data() {
    return {
      treeData: [
        {
          id: 1,
          title: '系统管理',
          type: '目录',
          path: '/system',
          route: '/system',
          component: '',
          status: '已注册',
          children: [
            {
              id: 2,
              title: '菜单管理',
              type: '菜单',
              path: '/system/menu',
              route: '/system/menu',
              component: 'SystemMenuList',
              status: '已注册',
              children: [
                {
                  id: 3,
                  title: '新增',
                  type: '按钮',
                  path: 'SystemMenuCreate',
                  route: 'SystemMenuCreate',
                  component: '',
                  status: '已注册'
                },
                {
                  id: 4,
                  title: '修改',
                  type: '按钮',
                  path: 'SystemMenuUpdate',
                  route: 'SystemMenuUpdate',
                  component: '',
                  status: '已注册'
                },
                {
                  id: 5,
                  title: '删除',
                  type: '按钮',
                  path: 'SystemMenuDelete',
                  route: 'SystemMenuDelete',
                  component: '',
                  status: '已注册'
                }
              ]
            },
            {
              id: 6,
              title: '角色管理',
              type: '菜单',
              path: '/system/role',
              route: '/system/role',
              component: '',
              status: '已注册'
            },
            {
              id: 7,
              title: '用户管理',
              type: '菜单',
              path: '/system/user',
              route: '/system/user',
              component: '',
              status: '已注册'
            }
          ]
        },
        {
          id: 8,
          title: '工作台',
          type: '页面',
          path: '/workspace',
          route: '/dashboard/workspace/index',
          component: '',
          status: '已注册'
        },
        {
          id: 9,
          title: '关于',
          type: '菜单',
          path: '/about',
          route: '/core/about/index',
          component: '',
          status: '已注册'
        }
      ],
      flatData: []
    }
  },
  created() {
    this.flatData = this.flattenTree(this.treeData)
  },
  methods: {
    flattenTree(nodes, level = 0, parent = null) {
      const result = []
      nodes.forEach(node => {
        this.$set(node, 'level', level)
        this.$set(node, 'parent', parent)
        this.$set(node, 'expanded', false)
        result.push(node)
        if (Array.isArray(node.children)) {
          result.push(...this.flattenTree(node.children, level + 1, node))
        }
      })
      return result
    },
    isVisible(row) {
      let parent = row.parent
      while (parent) {
        if (!parent.expanded) return false
        parent = parent.parent
      }
      return true
    },
    toggle(row) {
      row.expanded = !row.expanded
    },
    edit(row) {
      alert(`编辑:${row.title}`)
    },
    remove(row) {
      if (confirm(`确定删除 ${row.title} 吗?`)) {
        alert('删除成功(模拟)')
      }
    }
  }
}
</script>

<style scoped>
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
th, td {
  border: 1px solid #ddd;
  padding: 8px 12px;
  text-align: left;
}
.indent-0 { padding-left: 0; }
.indent-1 { padding-left: 20px; }
.indent-2 { padding-left: 40px; }
.indent-3 { padding-left: 60px; }
.toggle {
  cursor: pointer;
  margin-right: 5px;
  font-weight: bold;
}
.tag {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 12px;
  color: #fff;
}
.success { background-color: #67c23a; }
.info { background-color: #909399; }
.btn {
  padding: 4px 8px;
  font-size: 12px;
  margin-right: 4px;
  cursor: pointer;
  border: none;
  border-radius: 4px;
  background-color: #409eff;
  color: white;
}
.btn:hover {
  background-color: #66b1ff;
}
</style>
相关推荐
写不来代码的草莓熊1 小时前
vue前端面试题——记录一次面试当中遇到的题(9)
前端·javascript·vue.js
二十雨辰1 小时前
eduAi-智能体创意平台
前端·vue.js
郝学胜-神的一滴2 小时前
Three.js光照技术详解:为3D场景注入灵魂
开发语言·前端·javascript·3d·web3·webgl
m0dw2 小时前
vue懒加载
前端·javascript·vue.js·typescript
国家不保护废物2 小时前
手写 Vue Router,揭秘路由背后的魔法!🔮
前端·vue.js
小光学长3 小时前
基于Vue的保护动物信息管理系统r7zl6b88 (程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
麦麦大数据4 小时前
F029 vue游戏推荐大数据可视化系统vue+flask+mysql|steam游戏平台可视化
vue.js·游戏·信息可视化·flask·推荐算法·游戏推荐
cecyci4 小时前
如何实现AI聊天机器人的打字机效果?
前端·javascript
paopaokaka_luck5 小时前
基于SpringBoot+Vue的社区诊所管理系统(AI问答、webSocket实时聊天、Echarts图形化分析)
vue.js·人工智能·spring boot·后端·websocket
余道各努力,千里自同风5 小时前
el-input 输入框宽度自适应宽度
javascript·vue.js·elementui