当前位置:   article > 正文

Vue+Element中Table树形懒加载,添加,修改,删除后数据动态更新_element plus el-table 动态增加子树

element plus el-table 动态增加子树

数据准备

结果呈现

添加最外层菜单 

添加子菜单界面

直接上代码

index.vue

  1. <template>
  2. <div class="table-container">
  3. <vab-query-form>
  4. <vab-query-form-left-panel :span="3">
  5. <el-button icon="el-icon-plus" type="success" @click="handleAdd">
  6. 添加
  7. </el-button>
  8. </vab-query-form-left-panel>
  9. <vab-query-form-right-panel :span="21">
  10. <el-form
  11. ref="form"
  12. :inline="true"
  13. label-width="80px"
  14. :model="queryForm"
  15. @submit.native.prevent
  16. >
  17. <el-form-item label="品牌名称">
  18. <el-input
  19. v-model="queryForm.brandName"
  20. clearable
  21. placeholder="请输入品牌名称"
  22. style="width: 140px"
  23. />
  24. </el-form-item>
  25. <el-form-item>
  26. <el-button
  27. icon="el-icon-search"
  28. native-type="submit"
  29. type="primary"
  30. @click="handleQuery"
  31. >
  32. 查询
  33. </el-button>
  34. </el-form-item>
  35. </el-form>
  36. </vab-query-form-right-panel>
  37. </vab-query-form>
  38. <el-table
  39. :key="Math.random()"
  40. ref="tables"
  41. v-loading="listLoading"
  42. border
  43. :data="list"
  44. :default-expand-all="false"
  45. fit
  46. :height="height"
  47. lazy
  48. :load="loadChild"
  49. row-key="brandNo"
  50. :tree-props="{
  51. children: 'lstChildren',
  52. hasChildren: 'hasChildren',
  53. }"
  54. >
  55. <el-table-column
  56. label="品牌名称"
  57. prop="brandName"
  58. show-overflow-tooltip
  59. />
  60. <el-table-column label="品牌编码" prop="brandNo" show-overflow-tooltip />
  61. <el-table-column label="描述" prop="desr" show-overflow-tooltip />
  62. <el-table-column label="排序" prop="sort" show-overflow-tooltip />
  63. <el-table-column
  64. label="创建人名称"
  65. prop="createName"
  66. show-overflow-tooltip
  67. />
  68. <el-table-column label="操作">
  69. <template #default="{ row }">
  70. <el-button
  71. circle
  72. icon="el-icon-plus"
  73. size="mini"
  74. type="primary"
  75. @click="handleChildrenAdd(row)"
  76. />
  77. <el-button
  78. circle
  79. icon="el-icon-edit"
  80. size="mini"
  81. type="success"
  82. @click="handleEdit(row)"
  83. />
  84. <el-button
  85. circle
  86. icon="el-icon-delete"
  87. size="mini"
  88. type="danger"
  89. @click="handleDelete(row)"
  90. />
  91. </template>
  92. </el-table-column>
  93. </el-table>
  94. <el-pagination
  95. :background="background"
  96. :current-page="queryForm.pageModel.pageIndex"
  97. :layout="layout"
  98. :page-size="queryForm.pageModel.pageSize"
  99. :total="total"
  100. @current-change="handleCurrentChange"
  101. @size-change="handleSizeChange"
  102. />
  103. <brand-add-edit
  104. ref="edit"
  105. @fetch-data="fetchData"
  106. @fetch-edit-data="fetchEditData"
  107. />
  108. </div>
  109. </template>
  110. <script>
  111. import {
  112. get_brands_page,
  113. get_brands_all,
  114. brand_delete,
  115. } from '@/api/infoBrand'
  116. import BrandAddEdit from './components/brandAddEdit.vue'
  117. export default {
  118. name: 'Brand',
  119. components: { BrandAddEdit },
  120. data() {
  121. return {
  122. total: 0,
  123. layout: 'total, sizes, prev, pager, next, jumper',
  124. background: true,
  125. queryForm: {
  126. brandNo: '',
  127. brandName: '',
  128. parentNo: '',
  129. isDelete: false,
  130. pageModel: {
  131. pageIndex: 1,
  132. pageSize: 10,
  133. totalCount: 0,
  134. },
  135. },
  136. list: [],
  137. maps: new Map(),
  138. listLoading: true,
  139. currParentNo: '', //定义父级编码
  140. }
  141. },
  142. computed: {
  143. height() {
  144. return this.$baseTableHeight(1) + 30
  145. },
  146. },
  147. created() {
  148. this.fetchData()
  149. },
  150. mounted() {},
  151. methods: {
  152. //加载模块的数据
  153. async fetchData() {
  154. this.listLoading = true
  155. const { results, pageModel } = await get_brands_page(this.queryForm)
  156. this.list = results
  157. this.total = pageModel.totalCount
  158. setTimeout(() => {
  159. this.listLoading = false
  160. }, 500)
  161. },
  162. //懒加载
  163. async loadChild(tree, treeNode, resolve) {
  164. let _this = this
  165. const pid = tree.brandNo //取出当前的编码
  166. _this.maps.set(pid, { tree, treeNode, resolve }) //将当前选中节点数据存储到maps中
  167. get_brands_all({
  168. parentNo: pid,
  169. brandNo: '',
  170. brandName: '',
  171. }).then((res) => {
  172. if (res.results.length) {
  173. resolve(res.results)
  174. } else {
  175. resolve([])
  176. }
  177. })
  178. },
  179. fetchEditData(row) {
  180. let _this = this
  181. const { parentNo } = row
  182. if (_this.currParentNo) {
  183. //懒加载刷新当前菜单
  184. if (parentNo && _this.maps.get(parentNo)) {
  185. const { tree, treeNode, resolve } = _this.maps.get(parentNo)
  186. _this.loadChild(tree, treeNode, resolve)
  187. }
  188. //懒加载刷新父级
  189. if (_this.currParentNo && _this.maps.get(_this.currParentNo)) {
  190. const { tree, treeNode, resolve } = _this.maps.get(
  191. _this.currParentNo
  192. )
  193. _this.loadChild(tree, treeNode, resolve)
  194. }
  195. } else {
  196. _this.fetchData()
  197. }
  198. },
  199. handleDelete(row) {
  200. let _this = this
  201. _this.currParentNo = '' //清除父节点得历史数据
  202. _this.$baseConfirm('你确定要删除当前项吗?', null, async () => {
  203. const { msg, hasErr } = await brand_delete({
  204. brandNo: row.brandNo,
  205. isDelete: true,
  206. })
  207. _this.$baseMessage(msg, 'success')
  208. //重新获取所有菜单,更新vuex中得所有类目得最新数据
  209. _this.$store.dispatch(
  210. 'infobrand/updateBrandList',
  211. _this.$refs['edit'].brandForm
  212. )
  213. const { parentNo } = row //取出当前删除行的parentNo (父编码)
  214. //判断是否是一级删除
  215. if (parentNo) {
  216. const { tree, treeNode, resolve } = _this.maps.get(parentNo) //根据parentNo (父编码)取出对应的节点数据
  217. //将对应节点下的数据清空,从而实现数据的重新加载
  218. this.$set(
  219. _this.$refs.tables.store.states.lazyTreeNodeMap,
  220. parentNo,
  221. []
  222. )
  223. _this.currParentNo = tree.parentNo //获取当前父级编码进行重新加载节点
  224. _this.fetchEditData(tree)
  225. } else {
  226. //重新加载数据
  227. _this.fetchData()
  228. }
  229. })
  230. },
  231. handleAdd() {
  232. //最外层添加
  233. this.$refs['edit'].showEdit()
  234. },
  235. handleEdit(row) {
  236. this.$refs['edit'].showEdit(row)
  237. },
  238. handleChildrenAdd(row) {
  239. //添加子菜单
  240. this.$refs['edit'].showEdit(row, 'childrenAdd')
  241. },
  242. handleQuery() {
  243. this.queryForm.pageModel.pageIndex = 1
  244. this.fetchData()
  245. },
  246. handleSizeChange(val) {
  247. this.queryForm.pageModel.pageSize = val
  248. this.fetchData()
  249. },
  250. handleCurrentChange(val) {
  251. this.queryForm.pageModel.pageIndex = val
  252. this.fetchData()
  253. },
  254. },
  255. }
  256. </script>

 brandAddEdit.vue

  1. <template>
  2. <el-drawer
  3. :before-close="close"
  4. direction="rtl"
  5. :title="title"
  6. :visible.sync="dialogFormVisible"
  7. >
  8. <el-form
  9. ref="form"
  10. label-width="100px"
  11. :model="form"
  12. :rules="rules"
  13. style="padding: 20px"
  14. >
  15. <el-form-item label="父菜单" prop="brandNo">
  16. <el-cascader
  17. v-model.trim="form.brandNo"
  18. clearable
  19. :disabled="disabled"
  20. :options="brandList"
  21. placeholder="根目录"
  22. :props="{
  23. checkStrictly: true,
  24. children: 'lstChildren',
  25. value: 'brandNo',
  26. label: 'brandName',
  27. }"
  28. style="width: 100%"
  29. />
  30. </el-form-item>
  31. <el-form-item label="品牌名称" prop="brandName">
  32. <el-input
  33. v-model.trim="form.brandName"
  34. autocomplete="off"
  35. placeholder="输入品牌名称"
  36. />
  37. </el-form-item>
  38. <el-form-item label="描述" prop="desr">
  39. <el-input
  40. v-model.trim="form.desr"
  41. autocomplete="off"
  42. placeholder="输入描述"
  43. type="textarea"
  44. />
  45. </el-form-item>
  46. <el-form-item label="排序" prop="sort">
  47. <el-input
  48. v-model.trim="form.sort"
  49. autocomplete="off"
  50. placeholder="输入排序"
  51. />
  52. </el-form-item>
  53. <el-form-item>
  54. <el-button @click="close">取 消</el-button>
  55. <el-button type="primary" @click="save">确 定</el-button>
  56. </el-form-item>
  57. </el-form>
  58. </el-drawer>
  59. </template>
  60. <script>
  61. import { brand_save_or_update } from '@/api/infoBrand'
  62. import { mapGetters } from 'vuex'
  63. export default {
  64. name: 'BrandAddEdit',
  65. data() {
  66. return {
  67. form: {
  68. brandNo: '',
  69. brandName: '',
  70. sort: '',
  71. parentNo: '',
  72. desr: '',
  73. isDelete: false,
  74. },
  75. rules: {
  76. brandName: [
  77. { required: true, trigger: 'blur', message: '请输入品牌名称' },
  78. ],
  79. },
  80. title: '',
  81. pname: '根目录',
  82. dialogFormVisible: false,
  83. disabled: false,
  84. brandForm: {
  85. brandNo: '',
  86. brandName: '',
  87. parentNo: '',
  88. isDelete: false,
  89. },
  90. }
  91. },
  92. computed: {
  93. ...mapGetters({ brandList: 'infobrand/brandList' }),
  94. },
  95. created() {},
  96. mounted() {},
  97. methods: {
  98. showEdit(row, type) {
  99. this.disabled = false
  100. this.dialogFormVisible = true
  101. if (!row) {
  102. this.title = '当前全局添加'
  103. } else if (type == 'childrenAdd') {
  104. this.title = '添加子菜单'
  105. this.disabled = true //添加当前子菜单的时候不能选择其他类目
  106. this.form.brandNo = row.brandNo //回显
  107. this.form.parentNo = row.brandNo //一级添加子菜单的时候需要把当前编码作为添加时的父编码
  108. if (!row.parentNo) {
  109. //一级菜单添加
  110. this.$parent.currParentNo = row.parentNo
  111. } else {
  112. //当前节点添加 (如果当前父节点编码没有数据,就取当前节点编码为父级)
  113. this.$parent.currParentNo = row.parentNo || row.brandNo
  114. }
  115. } else {
  116. this.title = '编辑'
  117. this.disabled = true //编辑当前子菜单的时候不能选择其他类目
  118. this.form = Object.assign({}, row)
  119. }
  120. },
  121. close() {
  122. this.$refs['form'].resetFields()
  123. this.form = this.$options.data().form
  124. this.dialogFormVisible = false
  125. this.$emit('fetch-data')
  126. },
  127. save() {
  128. let _this = this
  129. _this.$refs['form'].validate(async (valid) => {
  130. if (valid) {
  131. const { parentNo } = _this.form
  132. if (_this.title == '编辑') {
  133. _this.$parent.currParentNo = _this.form.parentNo
  134. _this.getFormCommit(_this.form)
  135. } else {
  136. if (!parentNo) {
  137. //最外层添加
  138. _this.getFormCommit(_this.form)
  139. } else {
  140. //当前节点添加
  141. _this.form.brandNo = '' //在添加子菜单的时候需要把当前编码清空,因为添加编码是自动生成的,但是在回显的时候还是需要加上,添加就清空
  142. _this.getFormCommit(_this.form)
  143. }
  144. }
  145. } else {
  146. return false
  147. }
  148. })
  149. },
  150. //调用更新接口
  151. async getFormCommit(formdata) {
  152. let _this = this
  153. //添加和修改
  154. const { msg } = await brand_save_or_update(formdata)
  155. if (!formdata.parentNo) {
  156. //刷新一级菜单
  157. _this.$emit('fetch-data')
  158. } else {
  159. //添加成功后执行懒加载获取当前下得子菜单
  160. _this.$emit('fetch-edit-data', formdata)
  161. }
  162. //重新获取所有菜单,更新vuex中得所有类目得最新数据
  163. _this.$store.dispatch('infobrand/updateBrandList', _this.brandForm)
  164. //重置form表单
  165. _this.$refs['form'].resetFields()
  166. _this.form = _this.$options.data().form
  167. _this.dialogFormVisible = false
  168. _this.$baseMessage(msg, 'success')
  169. },
  170. },
  171. }
  172. </script>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/107588
推荐阅读
相关标签