element-ui 树形表格 懒加载 手风琴模式 拖动排序

当前vue2版本没有在优化,vue3版本更简洁

手风琴模式

实现的效果: 其中一个节点展开时,其他节点关闭,一直保持最多只有一个节点是展开的。

需要解决的问题: element-ui 树形懒加载表格自带的节点展开时,默认只有第一次才会触发load函数,之后在重新展开节点时,并不会触发load函数。

实现原理:同一个的节点多次重复操作展开子节点时只触发一次load加载函数。当一个节点的子节点展开时,其他节点的子节点收起,同时新展开的节点都需要触发load函数

手风琴模式: 根据element-ui文档创建树形表格
row-key : 用来优化 Table 的渲染;在使用 reserve-selection 功能与显示树形数据时,该属性是必填的
lazy : 开启懒加载模式
tree-props :指定哪些行是包含子节点
load :绑定节点加载函数

<template>
	<el-table ref="multipleTable" :data="list" row-key="id" lazy :load="load" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"></el-table>
</template>
<script>
	import { listCategoryfrom } form  '@/api/category'
	export default {
		data() {
			return {
				listQuery: {
					page: 1,
					limit: 10
				},
				list: []
			}
		},
		methods: {
			load(tree, treeNode, resolve) {
		        const newListQuery = JSON.parse(JSON.stringify(this.listQuery))
		        newListQuery.cid = tree.id
		        // 动态加载子节点数据
		        listCategory(newListQuery).then(response => {
		          this.$nextTick(function() {
		            this.list.map(item => {
		              if (item.id != tree.id) {
		                // 使用手风琴模式 expanded 控制子节点关闭还是开启,loaded设置为false,可以使树形表格每次都能加载
		                this.$set(this.$refs.multipleTable.store.states.treeData[item.id], 'loading', false)
		                this.$set(this.$refs.multipleTable.store.states.treeData[item.id], 'loaded', false)
		                this.$set(this.$refs.multipleTable.store.states.treeData[item.id], 'expanded', false)
		              }
		            })
		          })
		          resolve(response.data.data.items)
		        })
		     },
		}
	}
</script>

需要显示为手风琴模式,重点的代码是 this.$nextTick() 中的函数

this.$refs.multipleTable.store.states.treeData 获取所有父节点的状态

重新设置加载状态(这里是加载防止异常所以设置)
this. s e t ( t h i s . set(this. set(this.refs.multipleTable.store.states.treeData[item.id], ‘loading’, false)

重新设置节点未加载(手风琴重点代码,使load函数能够多次触发,解决了load不能多次触发的问题)
this. s e t ( t h i s . set(this. set(this.refs.multipleTable.store.states.treeData[item.id], ‘loaded’, false)

关闭已经打开的子节点 (expanded 为true 表示子节点展开, false 表示子节点关闭)
this. s e t ( t h i s . set(this. set(this.refs.multipleTable.store.states.treeData[item.id], ‘expanded’, false)

手风琴模式下的表格拖动排序

安装拖动插件 sortablejs
npm install sortablejs --save
在页面中引入
import Sortable from ‘sortablejs’

<template>
	<el-table ref="multipleTable" :data="list" row-key="id" lazy :load="load" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"></el-table>
</template>
<script>
	import Sortable from 'sortablejs'
	import { listCategoryfrom } form  '@/api/category'
	export default {
		data() {
			return {
				listQuery: {
					page: 1,
					limit: 10
				},
				list: []treeDate: {
	          		children: [],
	        		display: true,
	        		expanded: false,
	       		    lazy: true,
	       		    level: 0,
	      		    loaded: false,
	      		    loading: false
	     	   }
			}
		},
		mounted() {
    		  // 表格拖拽
  		   document.body.ondrop = function(event) {
     		   event.preventDefault();
    		   event.stopPropagation();
   		   }
     	   this.rowDrop()
  		},
		methods: {
			load(tree, treeNode, resolve) {
		        const newListQuery = JSON.parse(JSON.stringify(this.listQuery))
		        newListQuery.cid = tree.id
		        // 动态加载子节点数据
		        listCategory(newListQuery).then(response => {
		          this.$nextTick(function() {
		            this.list.map(item => {
		              if (item.id != tree.id) {
		                // 使用手风琴模式 expanded 控制子节点关闭还是开启,loaded设置为false,可以使树形表格每次都能加载
		                this.$set(this.$refs.multipleTable.store.states.treeData[item.id], 'loading', false)
		                this.$set(this.$refs.multipleTable.store.states.treeData[item.id], 'loaded', false)
		                this.$set(this.$refs.multipleTable.store.states.treeData[item.id], 'expanded', false)
		              }
		            })
		          })
		          resolve(response.data.data.items)
		        })
		     },
		     rowDrop() {
		     	// 获取表格节点
    		    const tbody = document.querySelector('.el-table__body-wrapper tbody')
     		    const _this = this
     		    // 插件调用函数
     		    Sortable.create(tbody, {
     		    	 // 拖拽开始时
       		   		 onStart({
         			   oldIndex
         		 	 }) {
          		  		 _this.list.forEach(item => {
          		 		 // 重新设置 treeData 的值,让表格行拖动的过程方向图标不会消失(由于重新渲染表格数据,这一行看个人需求是否添加)
             	 		 _this.$set(_this.$refs.multipleTable.store.states.treeData, item.id, _this.treeDate)
             	 		 // 置空子节点数据,保证拖拽时只计算一级节点的数量,否则会造成节点拖拽无法正确计算位置。 lazyTreeNodeMap 是存放子节点的数据
            	 		 _this.$set(_this.$refs.multipleTable.store.states.lazyTreeNodeMap, item.id, [])
          	  		  })
        		  },
        		  // 拖拽结束
         		  onEnd({
         		   newIndex, 
         		   oldIndex
         		  }) {
         		  	  // newIndex表格数据拖动后数据角标   oldIndex表格数据拖动前数据角标
           			  let from, end
          			  from = _this.list[oldIndex].id
        		      end = _this.list[newIndex].id
           			  // console.log(from, end)
           			  // 排序成功后重新获取数据 _this.list = [] 置空数据强制刷新数据,否则子节点数据无法更新,同时会出现bug ,使子节点出现在原来的位置
           			  // 后台排序,排序成功,重置数据
           			  paixu().then(res => {
           			    _this.list = []
           			    // 重新请求数据渲染
         		       _this.getList()
					 })
           			  
       			   }
     		   })
   		   },
		}
	}
</script>

你可能感兴趣的:(web前端,element-ui,vue,Sortable,拖拽排序,javascript)