Vue结合ElementUI封装一个树形结构的列表以及增删改查数据的弹窗(可直接复用)

话不多说直接上干货,大家可以直接根据需求改造后去复用

1.创建index文件 

<template>
  <div class="white-body-view">
    <!-- 树 -->
    <tree
      ref="customTree"
      :tree-data="treeData"
      :tree-expand-all="treeExpandAll"
      :tree-node-key="treeNodeKey"
      @handleCurrentNodeKeyClick="handleCurrentNodeKeyClick"
      @addTreeItem="addTreeItem"
      @addItem="addItem"
      @deleteItem="deleteItem"
      @editItem="editItem"
    />
    <!-- 树弹窗 -->
    <tree-dialog ref="treeDialog" @addData="addData" @editData="editData" />
  </div>
</template>
<script>
import Tree from '@/views/testTree/components/tree.vue'
import treeDialog from '@/views/testTree/components/treeDialog.vue'
export default {
  components: {
    Tree,
    treeDialog,
  },
  created() {
    this.getTreeList()
  },
  data() {
    return {
      treeData: [],
      treeExpandAll: true,
      treeNodeKey: 'treeId',
      treeId: '',
    }
  },
  methods: {
    // 树点击选中行
    handleCurrentNodeKeyClick(data) {
      this.currentNodeKey = data.treeId
    },
    // 新增表单数据
    addData(data) {
      // 新增树节点
      this.$refs.customTree.addItem(data)
      this.closeGroupDialog()
    },

    // 修改表单数据
    editData(data) {
      // 修改树节点
      this.$refs.customTree.editItem(data)
      // 调详情回显接口
      apt.getData({ id: data.treeId }).then((res) => {
        const { data } = res
        // 表单回显需要的参数
        this.treeParams.treeName = data.treeName
        this.treeParams.treeId = data.treeId
        this.treeParams.parentTreeId = data.parentTreeId
        this.treeParams.parentTreeName = data.parentTreeName
      })
    },
    //   添加主节点
    addTreeItem() {
      this.$refs.treeDialog.openDialog(1, false, '', {})
    },
    // 添加子节点
    addItem(data) {
      this.$refs.treeDialog.openDialog(0, false, data.treeId, data) //传递需要的参数
    },
    // ---删除树节点
    deleteItem(data) {
      this.$confirm('确认要删除当前节点吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          // 删除树节点
          // 根据需求修改调用接口的操作
          api.delete(data.treeId, 1).then((res) => {
            this.$message({ type: 'success', message: '删除成功' })
            this.$refs.customTree.treedeleteItem(data)
          })
        })
        .catch(() => {})
    },
    // 修改树节点
    editItem(data) {
      // 打开地点编辑弹窗
      this.$refs.treeDialog.openDialog(0, true, data.treeId, data) //传递需要的参数
    }
  }
}
</script>

2.引入 tree.vue文件

<template>
  <div class="container">
    <el-row class="container-block">
      <!-- 左侧树结构 -->
      <el-col :span="6" style="padding: 15px" class="tree-content">
        <el-input
          size="small"
          placeholder="请输入分组名称查询"
          suffix-icon="el-icon-search"
          v-model="filterText"
          class="tree-ipt"
          clearable
        >
        </el-input>
        <div class="left-container">
          <el-tree
            v-loading="treeLoading"
            :data="treeDataList"
            default-expand-all
            node-key="treeId"
            :highlight-current="true"
            :filter-node-method="filterNode"
            ref="fatherTree"
            @node-click="handleCurrentNodeKeyClick"
          >
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span class="txt-cont" :title="data.treeName">{{
                data.treeName
              }}</span>
              <span>
                <el-button
                  type="text"
                  v-if="node.level !== 3"
                  class="el-icon-plus"
                  size="mini"
                  @click="appendTreeGroup(data)"
                ></el-button>
                <el-button
                  type="text"
                  class="el-icon-delete"
                  size="mini"
                  @click="removeGroup(data)"
                ></el-button>
                <el-button
                  type="text"
                  class="el-icon-edit"
                  size="mini"
                  @click="editGroup(data)"
                ></el-button>
              </span>
            </span>
          </el-tree>
        </div>
        <div class="left-button">
          <el-button type="primary" @click="appendGroup()"
            >新增主分组</el-button
          >
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
export default {
  props: {
    // 源数据
    treeData: {
      type: Array,
      default: function () {
        return []
      },
    },

    // 树节点是否默认展开
    treeExpandAll: {
      type: Boolean,
      default: true,
    },

    // 树节点唯一标识
    treeNodeKey: {
      type: String,
      default: '',
    },
  },

  watch: {
    filterText(val) {
      this.$refs.fatherTree.filter(val)
    },
  },
  data() {
    return {
      filterText: '', //树查询
      treeType: '1', //标识符
      currentNodeKey: '', //选中treeId
      treeDataList: [], //
      treeId: '', //
      treeLoading: false, // 技能组树加载遮罩
      // 树级分组添加弹出框
      treeParams: {
        treeName: '', //分组名称
        type: '1', //分组添加类型:1加主分组,0加子分组
        treeType: '1', //分组类型标识符
        treeCode: '', //分组编码
        treeLevel: 1, //层级
        parentTreeId: '', //父级分组ID
        parentTreeName: '', //父级分组名称
        parentTreeCode: '', //父级分组编码
        children: [],
      },
      defaultProps: {
        children: 'children',
        label: 'name',
      },
      selectItem: {},
    }
  },
  created() {
    this.getTreeList()
  },
  methods: {
    // 获取树列表
    getTreeList() {
      this.treeLoading = true
      let params = {
        // 需要的参数
      }
      // 发起请求获取数据
      api
        .test(params)
        .then((res) => {
          const { data } = res
          this.treeDataList = data
          this.treeLoading = false
        })
        .catch((err) => {})
        .finally(() => {
          this.treeLoading = false
        })
    },
    // 添加主分组
    appendGroup() {
      this.$emit('addTreeItem')
    },
    // 添加子分组
    appendTreeGroup(data) {
      this.$emit('addItem', data)
    },
    // 点击删除按钮
    removeGroup(data) {
      this.$emit('deleteItem', data)
    },
    editGroup(data) {
      this.selectItem = data
      this.$emit('editItem', JSON.parse(JSON.stringify(data)))
    },
    // 过滤树
    filterNode(value, data) {
      if (!value) return true
      return data.treeName.indexOf(value) !== -1
    },
    // 树点击选中行
    handleCurrentNodeKeyClick(data) {
      this.$emit('handleCurrentNodeKeyClick', data)
    },
    //-----------------------------------父组件回调事件 开始=============

    // 添加新记录,树形列表回显
    treeAddItem(data) {
      this.$refs.tree.append(data, data.treeId)
    },

    // 删除节点
    treeDeleteItem(val) {
      this.$refs.tree.remove(val)
    },

    // 修改记录,树形列表回显
    editTreeItem(val) {
      Object.assign(this.selectItem, val)
      this.selectItem = {}
    },

    // ============== 父组件回调事件 结束=============
  },
}
</script>
<style lang="scss" scoped>
.container {
  background: #f2f6fc;
  padding: 13px;
  height: calc(100vh - 120px);
}
.container-block {
  height: 100%;
}
.left-container {
  height: calc(100% - 80px);
  overflow: auto;
}
.left-button {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}
.tree-content {
  background: white;
  border-radius: 4px;
  height: 100%;
}
.tree-ipt {
  margin-bottom: 8px;
}
.custom-tree-node {
  flex: 1;
  display: flex;
  width: 90%;
  align-items: center;
  justify-content: space-between;
  font-size: 14px !important;
  padding-right: 8px;
}

.custom-tree-node .txt-cont {
  display: inline-block;
  width: 186px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.container-query {
  margin: 16px 0 88px -40px;
}
.main-content {
  background: white;
  border-left: 8px solid #f2f6fc;
  border-radius: 4px;
  height: 100%;
}
.add-button {
  margin: -72px 0 8px 16px;
}
.container-table {
  margin: 16px;
}

.handle_edit {
  color: #1890ff;
  padding: 0;
}

.handle_del {
  color: #f5222d;
  padding: 0;
}
</style>

3.引入 treeDialog.vue文件

<template>
  <div>
    <el-dialog
      width="500px"
      :title="dialogName"
      :append-to-body="false"
      :visible.sync="dialogVisible"
      :close-on-click-modal="false"
    >
      <el-form
        ref="groupTreeTable"
        :model="treeParams"
        label-width="90px"
        size="small"
        :rules="rules"
      >
        <el-form-item
          label="分组名称"
          v-if="this.dialogName !== '添加子分组'"
          prop="treeName"
        >
          <el-input v-model="treeParams.treeName"></el-input>
        </el-form-item>
        <el-form-item
          v-if="this.dialogName == '添加子分组'"
          label="子分组名称"
          prop="treeName"
        >
          <el-input v-model="treeParams.treeName"></el-input>
        </el-form-item>
      </el-form>
      <!-- 弹出层按钮 -->
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitGroup">确 定</el-button>
        <el-button @click="closeGroupDialog">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    let that = this
    return {
      dialogVisible: false,
      dialogName: '', //增加分组弹窗
      // 树级分组添加弹出框
      treeType: '1',
      treeParams: {
        treeId: '', //分组类型标识符,
        treeName: '', //分组名称
        type: '1', //分组添加类型
        treeType: '1', //分组类型标识符,
        treeCode: '', //分组编码
        treeLevel: 1, //层级
        parentTreeId: '-', //父级分组ID
        parentTreeName: '-', //父级分组名称
        parentTreeCode: '', //父级分组编码
        children: [],
      },
      rules: {
        treeName: [
          { required: true, message: '请输入分组名称', trigger: 'blur' },
        ],
      },
      isEdit: false,
      data: {},
    }
  },
  methods: {
    openDialog(type, isEdit, treeId, data) {
      this.treeParams.type = type
      this.treeParams.treeId = treeId
      this.isEdit = isEdit
      this.data = data
      this.dialogVisible = true
      if (isEdit) {
        this.dialogName = '编辑分组'
        if (data.parentTreeId != '-') {
          type = '0'
        }
        // 调接口
        apt.test({ id: data.treeId }).then((res) => {
          const { data } = res
          this.treeParams.treeName = data.treeName
          this.treeParams.treeId = data.treeId

          this.treeParams.parentTreeId = data.parentTreeId
          this.treeParams.parentTreeName = data.parentTreeName
        })
      } else if (type == 0 && isEdit == false) {
        this.treeParams.type = '0'
        this.dialogName = '新增子分组'
        this.treeParams.parentTreeId = data.treeId
        this.treeParams.parentTreeName = data.treeName
        this.treeParams.treeLevel = parseInt(data.treeLevel) + 1
      } else {
        this.treeParams.type = '1'
        this.dialogName = '新增主分组'
        this.treeParams.parentTreeId = '-'
        this.treeParams.parentTreeName = '-'
      }
    },
    // 提交表单
    submitGroup() {
      this.$refs.groupTreeTable.validate((valid) => {
        if (valid) {
          let treeParams = {
            //  需要的参数
          }
          let updataTreeParams = {
            // 需要的参数
          }
          //  todo:调接口的操作
        }
      })
    },
    // 关闭当前弹窗
    closeGroupDialog() {
      this.clearTreeDialog()
      this.dialogVisible = false
    },
    clearTreeDialog() {
      this.addDialogVisible = false
      this.dialogName = ''
      this.treeParams.treeName = ''
    },
  },
}
</script>
<style scoped>
.pull-right {
  float: right;
}
</style>

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以按照以下步骤使用Vue 2和Element UI创建一个具有增删改查、状态开关和展开功能的表格: 1. 首先,确保你已经安装了VueElement UI库。你可以使用npm或yarn来安装它们: ```bash npm install vue@2.6.14 npm install element-ui@2.15.6 ``` 2. 创建一个Vue组件,用于显示表格和处理相关逻辑。在该组件中,你可以定义数据、方法和计算属性。 ```vue <template> <div> <el-table :data="tableData" style="width: 100%"> <el-table-column label="编号" prop="id"></el-table-column> <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="状态"> <template slot-scope="scope"> <el-switch v-model="scope.row.status"></el-switch> </template> </el-table-column> <el-table-column> <template slot-scope="scope"> <el-button @click="handleExpand(scope.row)" type="text">展开</el-button> </template> </el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button @click="handleEdit(scope.row)" type="text">编辑</el-button> <el-button @click="handleDelete(scope.row)" type="text">删除</el-button> </template> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { tableData: [ { id: 1, name: '张三', status: false }, { id: 2, name: '李四', status: true }, { id: 3, name: '王五', status: true } ] }; }, methods: { handleEdit(row) { // 处理编辑操作 }, handleDelete(row) { // 处理删除操作 }, handleExpand(row) { // 处理展开操作 } } }; </script> ``` 3. 在你的Vue入口文件中,引入VueElement UI,并注册Element UI组件。 ```javascript import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue'; Vue.use(ElementUI); new Vue({ render: h => h(App) }).$mount('#app'); ``` 这样,你就可以在Vue应用中使用Element UI的表格组件,并实现增删改查、状态开关和展开功能了。你可以根据需要在`handleEdit`、`handleDelete`和`handleExpand`方法中编写相应的逻辑。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值