vue+element-ui el-tree 组件 的动态加载、新增、更新节点

本文介绍了如何在Vue+Element-UI中使用el-tree组件进行动态加载数据、新增和更新节点的操作。文章通过示例展示了如何处理后台返回的数据,并利用loadNode方法动态加载节点,同时讨论了对组件样式的个性化调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue+element-ui el-tree 组件 的动态加载、新增、更新节点

最近在根据需求,需要用到树形控件,ele 的封装了树形控件正好拿来用,用的途中遇到一些问题就总结下,哈哈哈

说正事,我需要动态的加载出整个树形结构,刚好就有在这里插入图片描述
符合需求,啦啦啦
用的时候出现问题了,我要如何把后台返回个我的数据加载到表里呢,上菜。。。

<template>
	<el-tree
      empty-text="暂无数据"
      :expand-on-click-node="false"
      :props="defaultProps"
      :load="loadNode"
      node-key="id"
      lazy>
      <div class="custom-tree-node" slot-scope="{ node, data }">
        <div class="fl"><i class="el-icon-menu"></i>{{ node.label }}</div>
        <div class="fr">
          <el-button
            type="primary"
            size="mini"
            @click="() => addDialogShow(node, data, 0)">
            新增
          </el-button>
          <el-button
            type="primary"
            plain 
            size="mini"
            @click="() => addDialogShow(node, data, 1)">
            更新
          </el-button>
          <!-- <el-button
            disabled
            type="danger"
            size="mini"
            @click="() => remove(node, data)">
            删除
          </el-button> -->
        </div>
      </div>
    </el-tree>
</template>

el-tree 标准样式了

部分

<script>
  import { typeList, addtype, updatetype, deltype } from '@/api/baseType'

  export default {
    data() {
      return {
        defaultProps: {
            id: "Id",
            label: 'Name',
            children: 'children'
        },
        //新增相关
        addDialog:false,
        addForm: {},
        addRules:{
          name:[{required: true,message: '请输入基础类型名',trigger: 'blur'}]
        },
        pid: null, // 基础类型得父级id
        flag: null, //操作标志位
        node: {}, // tree 节点对象
        nodedata: {} 
      }
    },
    created(){
    },
    methods: {
      // 加载树结点
      loadNode(node, resolve) {
        // 如果是顶级的父节点
        if (node.level === 0) {
          // 查找顶级对象
          typeList(node.level).then(res => {
            if (res.Data) {
              return resolve(res.Data)
            } else {
              this.$message.error(res.Msg)
            }
          }).catch(() => {
            let data = []
            return resolve(data)
          })
        } else {
          // 根据父节点id找寻下一级的所有节点 
          typeList(node.data.Id).then(res => {
            if (res.Data) {
              return resolve(res.Data)
            } else {
              this.$message.error(res.Msg)
            }
          }).catch(() => {
            let data = []
            return resolve(data)
          })
        }
      },
      remove(node, data) {
        console.log(node, data)
        // const parent = node.parent;
        // const children = parent.data.children || parent.data;
        // const index = children.findIndex(d => d.id === data.id);
        // children.splice(index, 1);
      },
      //新增
      addDialogShow(node,data,flag) {
        this.node = node //
        this.nodedata = data
        if(flag === 0) {
          this.addDialog = true
          this.pid = data.Id
          this.flag = 0
        }
        if(flag === 1) {
          this.addDialog = true
          this.pid = data.Id
          this.addForm.name = data.Name
          this.flag = 1
        }
      },
      addSubmit(flag) {
        this.$refs.addForm.validate((valid) => {
          if(valid){
            this.listLoading = true
            let arr = Object.assign({}, this.addForm)
            console.log(flag)
            if(flag === 0) {
              let data = {
                pid: this.pid,
                name: arr.name
              }
              // 新增 api
              addtype(data).then(() => {
                typeList(data.pid).then(res => {
                  let id = res.Data[0].Id 
                  const newChild = { id: id, label: arr.name, children: [] };
                  if (!this.nodedata.children) {
                    this.$set(nodedata, 'children', []);
                  }
                  this.nodedata.children.push(newChild)
                  this.addDialog = false
                  this.$notify.success({
                    message:'新增成功',
                    duration: 2000
                  })
                })
              }).catch(() => {
                this.addDialog = false
              })
            }
            if(flag === 1) {
              let data = {
                name: arr.name
              }
              updatetype(this.pid,data).then(res => {
                this.$set(this.node.data, 'Name',arr.name)
                this.addDialog = false
                this.$notify.success({
                  message:'更新成功',
                  duration: 2000
                })
              }).catch(() => {
                this.addDialog = false
              })
            }
          }
        })
      }
    }
  }
</script>

动态的加载树形数据 这里通过对ele 提供的方法
这里对 el-tree 的样式做了些许的改变
这个看个人需要了

<style lang="less" scoped>
  .el-tree-node__content {
    line-height: 50px;
    .custom-tree-node {
      width: 100%;
      display: block;
      .fl {
        float: left;
        line-height: 31px;
      }
      .fr {
        float: right;
        margin-right: 50px;
      }
    }
  }
</style>

动态加载节点数据,这里通过 ele 提供的 loadNode() 方法 可以根据个人需要改写

 这里我是用弹出框进行信息的管理
 实现动态的后台数据更新 和 前台显示的刷新,
addDialogShow(node,data,flag) {
	this.node = node // 这里对nodetree 进行了预先存储
    this.nodedata = data
}

在这里插入图片描述

然后 在更行后台api 成功后 通过 Vue.$set() 刷新子节点数据
 let arr = Object.assign({}, this.addForm) //获取输入框输入的数据

 updatetype(this.pid,data).then(res => {
     this.$set(this.node.data, 'Name',arr.name)  //同步刷新
     this.addDialog = false
     this.$notify.success({
       message:'更新成功',
       duration: 2000
     })
   }).catch(() => {
     this.addDialog = false
   })
 }

有更好的方法,欢迎留言交流!!!

要实现一个无限级动态菜单,可以使用 Element UITree 组件。以下是一个简单的实现示例: 首先,需要在 Vue 中引入 Element UITree 组件: ```javascript import { Tree } from 'element-ui'; ``` 然后,可以在 Vue 的模板中使用 `el-tree` 标签来渲染 Tree 组件: ```html <el-tree :data="menuData" :props="treeProps" @node-click="handleNodeClick"></el-tree> ``` 其中,`menuData` 是菜单数据,`treeProps` 是 Tree 组件的属性配置对象,`handleNodeClick` 是 Tree 组件的点击事件处理函数。 接下来,我们来看一下如何实现动态加载菜单数据。首先,需要在 Vue 的 `mounted` 生命周期中调用一个方法来获取菜单数据: ```javascript mounted() { this.getMenuData(); }, methods: { getMenuData() { // 通过接口获取菜单数据 } } ``` 接着,在菜单数据获取成功后,需要将数据转换成符合 Tree 组件要求的格式,并将数据保存在 Vue 实例的 `menuData` 属性中: ```javascript getMenuData() { // 通过接口获取菜单数据 // 将数据转换成符合 Tree 组件要求的格式 const menuData = convertMenuData(data); // 将数据保存在 Vue 实例的 menuData 属性中 this.menuData = menuData; } ``` 最后,我们来看一下如何处理 Tree 组件的点击事件。在 `handleNodeClick` 方法中,可以根据节点的 `level` 属性来判断当前节点是否为叶子节点。如果是叶子节点,则可以执行相应的操作,比如打开对应的页面;否则,需要递归获取子节点的数据并更新 Tree 组件的数据源: ```javascript handleNodeClick(node) { if (node.level === 2) { // 点击了叶子节点,执行相应操作 // 比如打开对应的页面 window.location.href = node.url; } else { // 点击了非叶子节点,递归获取子节点数据并更新 Tree 组件的数据源 const childNodes = await this.getChildNodes(node); node.children = childNodes; this.menuData = [...this.menuData]; } }, async getChildNodes(node) { // 通过接口获取子节点数据 const childNodesData = await getChildrenData(node.id); // 将数据转换成符合 Tree 组件要求的格式 const childNodes = convertMenuData(childNodesData); return childNodes; } ``` 至此,一个简单的无限级动态菜单就实现了。完整的代码可以参考下面的示例: ```html <template> <el-tree :data="menuData" :props="treeProps" @node-click="handleNodeClick"></el-tree> </template> <script> import { Tree } from 'element-ui'; export default { components: { [Tree.name]: Tree }, data() { return { menuData: [], treeProps: { label: 'name', children: 'children' } }; }, mounted() { this.getMenuData(); }, methods: { async getMenuData() { // 通过接口获取菜单数据 const data = await getMenuData(); // 将数据转换成符合 Tree 组件要求的格式 const menuData = convertMenuData(data); // 将数据保存在 Vue 实例的 menuData 属性中 this.menuData = menuData; }, async handleNodeClick(node) { if (node.level === 2) { // 点击了叶子节点,执行相应操作 // 比如打开对应的页面 window.location.href = node.url; } else { // 点击了非叶子节点,递归获取子节点数据并更新 Tree 组件的数据源 const childNodes = await this.getChildNodes(node); node.children = childNodes; this.menuData = [...this.menuData]; } }, async getChildNodes(node) { // 通过接口获取子节点数据 const childNodesData = await getChildrenData(node.id); // 将数据转换成符合 Tree 组件要求的格式 const childNodes = convertMenuData(childNodesData); return childNodes; } } }; </script> ```
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值