Vue+Element中Table树形懒加载,添加,修改,删除后数据动态更新

数据准备

结果呈现

添加最外层菜单 

添加子菜单界面

直接上代码

index.vue

<template>
  <div class="table-container">
    <vab-query-form>
      <vab-query-form-left-panel :span="3">
        <el-button icon="el-icon-plus" type="success" @click="handleAdd">
          添加
        </el-button>
      </vab-query-form-left-panel>
      <vab-query-form-right-panel :span="21">
        <el-form
          ref="form"
          :inline="true"
          label-width="80px"
          :model="queryForm"
          @submit.native.prevent
        >
          <el-form-item label="品牌名称">
            <el-input
              v-model="queryForm.brandName"
              clearable
              placeholder="请输入品牌名称"
              style="width: 140px"
            />
          </el-form-item>
          <el-form-item>
            <el-button
              icon="el-icon-search"
              native-type="submit"
              type="primary"
              @click="handleQuery"
            >
              查询
            </el-button>
          </el-form-item>
        </el-form>
      </vab-query-form-right-panel>
    </vab-query-form>
    <el-table
      :key="Math.random()"
      ref="tables"
      v-loading="listLoading"
      border
      :data="list"
      :default-expand-all="false"
      fit
      :height="height"
      lazy
      :load="loadChild"
      row-key="brandNo"
      :tree-props="{
        children: 'lstChildren',
        hasChildren: 'hasChildren',
      }"
    >
      <el-table-column
        label="品牌名称"
        prop="brandName"
        show-overflow-tooltip
      />
      <el-table-column label="品牌编码" prop="brandNo" show-overflow-tooltip />
      <el-table-column label="描述" prop="desr" show-overflow-tooltip />
      <el-table-column label="排序" prop="sort" show-overflow-tooltip />
      <el-table-column
        label="创建人名称"
        prop="createName"
        show-overflow-tooltip
      />
      <el-table-column label="操作">
        <template #default="{ row }">
          <el-button
            circle
            icon="el-icon-plus"
            size="mini"
            type="primary"
            @click="handleChildrenAdd(row)"
          />

          <el-button
            circle
            icon="el-icon-edit"
            size="mini"
            type="success"
            @click="handleEdit(row)"
          />
          <el-button
            circle
            icon="el-icon-delete"
            size="mini"
            type="danger"
            @click="handleDelete(row)"
          />
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      :background="background"
      :current-page="queryForm.pageModel.pageIndex"
      :layout="layout"
      :page-size="queryForm.pageModel.pageSize"
      :total="total"
      @current-change="handleCurrentChange"
      @size-change="handleSizeChange"
    />
    <brand-add-edit
      ref="edit"
      @fetch-data="fetchData"
      @fetch-edit-data="fetchEditData"
    />
  </div>
</template>
<script>
  import {
    get_brands_page,
    get_brands_all,
    brand_delete,
  } from '@/api/infoBrand'
  import BrandAddEdit from './components/brandAddEdit.vue'
  export default {
    name: 'Brand',
    components: { BrandAddEdit },
    data() {
      return {
        total: 0,
        layout: 'total, sizes, prev, pager, next, jumper',
        background: true,
        queryForm: {
          brandNo: '',
          brandName: '',
          parentNo: '',
          isDelete: false,
          pageModel: {
            pageIndex: 1,
            pageSize: 10,
            totalCount: 0,
          },
        },
        list: [],
        maps: new Map(),
        listLoading: true,
        currParentNo: '', //定义父级编码
      }
    },
    computed: {
      height() {
        return this.$baseTableHeight(1) + 30
      },
    },
    created() {
      this.fetchData()
    },
    mounted() {},
    methods: {
      //加载模块的数据
      async fetchData() {
        this.listLoading = true
        const { results, pageModel } = await get_brands_page(this.queryForm)
        this.list = results
        this.total = pageModel.totalCount
        setTimeout(() => {
          this.listLoading = false
        }, 500)
      },
      //懒加载
      async loadChild(tree, treeNode, resolve) {
        let _this = this
        const pid = tree.brandNo //取出当前的编码
        _this.maps.set(pid, { tree, treeNode, resolve }) //将当前选中节点数据存储到maps中
        get_brands_all({
          parentNo: pid,
          brandNo: '',
          brandName: '',
        }).then((res) => {
          if (res.results.length) {
            resolve(res.results)
          } else {
            resolve([])
          }
        })
      },
      fetchEditData(row) {
        let _this = this
        const { parentNo } = row
        if (_this.currParentNo) {
          //懒加载刷新当前菜单
          if (parentNo && _this.maps.get(parentNo)) {
            const { tree, treeNode, resolve } = _this.maps.get(parentNo)
            _this.loadChild(tree, treeNode, resolve)
          }
          //懒加载刷新父级
          if (_this.currParentNo && _this.maps.get(_this.currParentNo)) {
            const { tree, treeNode, resolve } = _this.maps.get(
              _this.currParentNo
            )
            _this.loadChild(tree, treeNode, resolve)
          }
        } else {
          _this.fetchData()
        }
      },
      handleDelete(row) {
        let _this = this
        _this.currParentNo = '' //清除父节点得历史数据
        _this.$baseConfirm('你确定要删除当前项吗?', null, async () => {
          const { msg, hasErr } = await brand_delete({
            brandNo: row.brandNo,
            isDelete: true,
          })
          _this.$baseMessage(msg, 'success')
          //重新获取所有菜单,更新vuex中得所有类目得最新数据
          _this.$store.dispatch(
            'infobrand/updateBrandList',
            _this.$refs['edit'].brandForm
          )
          const { parentNo } = row //取出当前删除行的parentNo (父编码)
          //判断是否是一级删除
          if (parentNo) {
            const { tree, treeNode, resolve } = _this.maps.get(parentNo) //根据parentNo (父编码)取出对应的节点数据
            //将对应节点下的数据清空,从而实现数据的重新加载
            this.$set(
              _this.$refs.tables.store.states.lazyTreeNodeMap,
              parentNo,
              []
            )
            _this.currParentNo = tree.parentNo //获取当前父级编码进行重新加载节点
            _this.fetchEditData(tree)
          } else {
            //重新加载数据
            _this.fetchData()
          }
        })
      },
      handleAdd() {
        //最外层添加
        this.$refs['edit'].showEdit()
      },
      handleEdit(row) {
        this.$refs['edit'].showEdit(row)
      },
      handleChildrenAdd(row) {
        //添加子菜单
        this.$refs['edit'].showEdit(row, 'childrenAdd')
      },
      handleQuery() {
        this.queryForm.pageModel.pageIndex = 1
        this.fetchData()
      },
      handleSizeChange(val) {
        this.queryForm.pageModel.pageSize = val
        this.fetchData()
      },
      handleCurrentChange(val) {
        this.queryForm.pageModel.pageIndex = val
        this.fetchData()
      },
    },
  }
</script>

 brandAddEdit.vue

<template>
  <el-drawer
    :before-close="close"
    direction="rtl"
    :title="title"
    :visible.sync="dialogFormVisible"
  >
    <el-form
      ref="form"
      label-width="100px"
      :model="form"
      :rules="rules"
      style="padding: 20px"
    >
      <el-form-item label="父菜单" prop="brandNo">
        <el-cascader
          v-model.trim="form.brandNo"
          clearable
          :disabled="disabled"
          :options="brandList"
          placeholder="根目录"
          :props="{
            checkStrictly: true,
            children: 'lstChildren',
            value: 'brandNo',
            label: 'brandName',
          }"
          style="width: 100%"
        />
      </el-form-item>
      <el-form-item label="品牌名称" prop="brandName">
        <el-input
          v-model.trim="form.brandName"
          autocomplete="off"
          placeholder="输入品牌名称"
        />
      </el-form-item>
      <el-form-item label="描述" prop="desr">
        <el-input
          v-model.trim="form.desr"
          autocomplete="off"
          placeholder="输入描述"
          type="textarea"
        />
      </el-form-item>
      <el-form-item label="排序" prop="sort">
        <el-input
          v-model.trim="form.sort"
          autocomplete="off"
          placeholder="输入排序"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="close">取 消</el-button>
        <el-button type="primary" @click="save">确 定</el-button>
      </el-form-item>
    </el-form>
  </el-drawer>
</template>
<script>
  import { brand_save_or_update } from '@/api/infoBrand'
  import { mapGetters } from 'vuex'
  export default {
    name: 'BrandAddEdit',
    data() {
      return {
        form: {
          brandNo: '',
          brandName: '',
          sort: '',
          parentNo: '',
          desr: '',
          isDelete: false,
        },
        rules: {
          brandName: [
            { required: true, trigger: 'blur', message: '请输入品牌名称' },
          ],
        },
        title: '',
        pname: '根目录',
        dialogFormVisible: false,
        disabled: false,
        brandForm: {
          brandNo: '',
          brandName: '',
          parentNo: '',
          isDelete: false,
        },
      }
    },
    computed: {
      ...mapGetters({ brandList: 'infobrand/brandList' }),
    },
    created() {},
    mounted() {},
    methods: {
      showEdit(row, type) {
        this.disabled = false
        this.dialogFormVisible = true
        if (!row) {
          this.title = '当前全局添加'
        } else if (type == 'childrenAdd') {
          this.title = '添加子菜单'
          this.disabled = true //添加当前子菜单的时候不能选择其他类目
          this.form.brandNo = row.brandNo //回显
          this.form.parentNo = row.brandNo //一级添加子菜单的时候需要把当前编码作为添加时的父编码
          if (!row.parentNo) {
            //一级菜单添加
            this.$parent.currParentNo = row.parentNo
          } else {
            //当前节点添加 (如果当前父节点编码没有数据,就取当前节点编码为父级)
            this.$parent.currParentNo = row.parentNo || row.brandNo
          }
        } else {
          this.title = '编辑'
          this.disabled = true //编辑当前子菜单的时候不能选择其他类目
          this.form = Object.assign({}, row)
        }
      },
      close() {
        this.$refs['form'].resetFields()
        this.form = this.$options.data().form
        this.dialogFormVisible = false
        this.$emit('fetch-data')
      },
      save() {
        let _this = this
        _this.$refs['form'].validate(async (valid) => {
          if (valid) {
            const { parentNo } = _this.form
            if (_this.title == '编辑') {
              _this.$parent.currParentNo = _this.form.parentNo
              _this.getFormCommit(_this.form)
            } else {
              if (!parentNo) {
                //最外层添加
                _this.getFormCommit(_this.form)
              } else {
                //当前节点添加
                _this.form.brandNo = '' //在添加子菜单的时候需要把当前编码清空,因为添加编码是自动生成的,但是在回显的时候还是需要加上,添加就清空
                _this.getFormCommit(_this.form)
              }
            }
          } else {
            return false
          }
        })
      },
      //调用更新接口
      async getFormCommit(formdata) {
        let _this = this
        //添加和修改
        const { msg } = await brand_save_or_update(formdata)
        if (!formdata.parentNo) {
          //刷新一级菜单
          _this.$emit('fetch-data')
        } else {
          //添加成功后执行懒加载获取当前下得子菜单
          _this.$emit('fetch-edit-data', formdata)
        }
        //重新获取所有菜单,更新vuex中得所有类目得最新数据
        _this.$store.dispatch('infobrand/updateBrandList', _this.brandForm)
        //重置form表单
        _this.$refs['form'].resetFields()
        _this.form = _this.$options.data().form
        _this.dialogFormVisible = false
        _this.$baseMessage(msg, 'success')
      },
    },
  }
</script>

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
删除 el-table 树形数据的当前行,可以使用以下步骤: 1. 首先,在当前行上添加一个删除按钮或其他交互元素。你可以使用 el-table-column 的自定义模板来实现这一点。 2. 在点击删除按钮时,获取当前行的数据。你可以使用 $refs 属性引用 el-table 组件,并使用 $refs.table.getCurrentRow() 方法获取当前行数据。 3. 在获取到当前行数据后,你需要使用递归的方式删除当前行及其所有子行。可以编写一个递归函数,遍历当前行的子节点,将其从数据删除。 4. 最后,更新 el-table 组件的数据源,以反映删除操作的结果。可以使用 Vue.set() 方法来更新数据源,确保删除操作能够触发响应式更新。 以下是一个示例代码片段,演示如何删除 el-table 树形数据的当前行: ```html <template> <el-table :data="tableData" ref="table" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @row-remove="handleRowRemove"> <el-table-column label="名称" prop="name"></el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button v-if="scope.row.hasChildren" type="text" @click="handleRemoveRow(scope.row)">删除</el-button> </template> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { name: '节点1', children: [ { name: '子节点1', hasChildren: false }, { name: '子节点2', hasChildren: false } ], hasChildren: true }, { name: '节点2', children: [ { name: '子节点3', hasChildren: true, children: [ { name: '子节点4', hasChildren: false } ] } ], hasChildren: true } ] } }, methods: { handleRemoveRow(row) { this.$refs.table.remove(row) }, handleRowRemove(row, rowIndex) { this.recursiveRemove(row) }, recursiveRemove(row) { for (let i = 0; i < row.children.length; i++) { this.recursiveRemove(row.children[i]) } const parent = this.getParentNode(row) const index = parent.children.indexOf(row) parent.children.splice(index, 1) Vue.set(parent, 'children', parent.children) }, getParentNode(row) { const stack = [this.tableData[0]] while (stack.length) { const node = stack.pop() if (node.children && node.children.indexOf(row) !== -1) { return node } if (node.children) { for (let i = 0; i < node.children.length; i++) { stack.push(node.children[i]) } } } return null } } } </script> ``` 在上述示例,我们使用 el-button 按钮作为删除交互元素,并在 @click 事件调用 handleRemoveRow 方法。在 handleRemoveRow 方法,我们使用 this.$refs.table.remove(row) 方法删除当前行。在 handleRowRemove 方法,我们调用 recursiveRemove 方法递归地删除当前行及其子行。最后,我们使用 Vue.set() 方法更新数据源,以确保删除操作能够触发响应式更新
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑色咖啡 Ken

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

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

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

打赏作者

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

抵扣说明:

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

余额充值