Element中Tree树结构组件中实现Ctrl和Shift多选

博客 分享
0 136
张三
张三 2022-05-19 14:59:24
悬赏:0 积分 收藏

Element中Tree树结构组件中实现Ctrl和Shift多选

  在Element中的树结构中, 实现多选功能,首先的是判断有没有按下键盘ctrl和shift按键。但是在Element中的tree组件的左键点击事件是没有提供$event鼠标属性判断的。所以就需要在函数中使用自身的$event来判断。请看树结构下面左键和右键点击的函数传参的截图。

 

  所以,左键的点击函数,需要自行判断。如下代码示例

<el-tree     class="filter-tree"     :load="loadNode"     lazy     :props="defaultProps"     :filter-node-method="filterNode"     :render-content="renderContent"     ref="treeRef"     :expand-on-click-node="false"     @node-contextmenu="rightClick"     @node-click="leftClick" // 左键点击事件     :highlight-current="true"     node-key="id"     :check-on-click-node="true"     :show-checkbox="false"     check-strictly></el-tree>

里面的左键函数,是这样的

 1   methods: { 2     leftClick(data, node, dom) { 3       let event = window.event || arguments.callee.caller.arguments[0]; 4       var ctrlKeyDowned = event.ctrlKey; 5       var shiftKeyDowned = event.shiftKey; 6       // 走单击事件 7  8       var allTreeNode = this.$refs.treeRef.getNode(1); 9       this.clickTime = "";10       if (ctrlKeyDowned == false && shiftKeyDowned == false) { // 都没有点击11         this.cancelSelectTree(); // 取消原来的选中12         this.leftTreeSelectedArr.splice(0);13         this.leftTreeSelectedArr.push(data);14       } else if (ctrlKeyDowned == true && shiftKeyDowned == false) { // 只点击ctrl15         this.$set(data, "Selected", true);16         var isIN = this.leftTreeSelectedArr.every(item => {17           return item.id != data.id;18         });19         isIN && this.leftTreeSelectedArr.push(data);20         if (!isIN) {21           // 如果已经是选中的了,那么应该取消选择22           data.Selected = false;23           this.leftTreeSelectedArr.map((item, i) => {24             if (item.id == data.id) {25               this.leftTreeSelectedArr.splice(i, 1);26               this.$refs.treeRef.setCurrentKey(); // 取消高亮,要不然区分不出来,是不是没有选中27             }28           });29         }30       } else if (ctrlKeyDowned == false && shiftKeyDowned == true) { // 只点击shift31         this.delayeringArr.splice(0);32         this.delayering([allTreeNode]); // 把现在展开的数据都扁平化33         this.$set(data, "Selected", true);34         this.leftTreeSelectedArr.push(data);35         this.shiftTree(); // shifit多选36       }37     }38   }

通过,第三行中的内容,获取到鼠标的点击事件属性,然后从中获取到是都点击了键盘的Ctrl和Shift;

  Ctrl多选就不用过多的介绍了,把点击树结构的内容, 通过去重判断,直接放在leftTreeSelectedArr中就可以了。这里就不做过多的介绍了。具体请看,14至30行代码。下面主要是讲解一下,shift多选。

  Shfit多选,在平常的列表中是很好实现的。我们可以把所有的数据,放在一个一维的数组中,那么任意选择其中的两项的话,就能把数组分割成为三部分。其中的中间部分,也就是第二部分就是Shift多选的结果。请看下面的草图

但是对于树结构的话,就稍微的麻烦一点了,树结构的数据是这样的。

那么他的真实的数据格式应该是这样的。

 1 treeData: [ 2         { 3           id: 1, 4           name: "1节点", 5           childrenId: [ 6             { 7               id: 2, 8               name: "2节点", 9               childrenId: [10                 {11                   id: 5,12                   name: "5节点",13                   childrenId: []14                 },15                 {16                   id: 6,17                   name: "6节点",18                   childrenId: []19                 }20               ]21             },22             {23               id: 3,24               name: "3节点",25               childrenId: [26                 {27                   id: 7,28                   name: "7节点",29                   childrenId: []30                 }31               ]32             },33             {34               id: 4,35               name: "4节点",36               childrenId: [37                 {38                   id: 8,39                   name: "8节点",40                   childrenId: []41                 },42                 {43                   id: 9,44                   name: "9节点",45                   childrenId: []46                 },47                 {48                   id: 10,49                   name: "10节点",50                   childrenId: [51                     {52                       id: 11,53                       name: "11节点",54                       childrenId: []55                     },56                     {57                       id: 12,58                       name: "12节点",59                       childrenId: []60                     }61                   ]62                 }63               ]64             }65           ]66         }67       ]

那么树结构在页面上渲染完成之后就是这样的:

 

那shift多选是怎么判断的呢,怎么知道这个层级是属于哪个呢,怎么知道这个层级下面的内容需不需选中呢,如果展开了,就是应该选中的,如果没有展开是不是就不需要选中呢。所以的这些问题,如果思考下来的话, 确实比较复杂,如果遍历的话,也是很难的。任意选中两个之后,都不知道应该是向上查找遍历,还是向下查找遍历。所以遍历的话,是不可用的,或者说是不太容易实现的。

  回到问题的本质,在一维的数组,shif多选是很简单的。那么这个树形结构是不是也可以转换成一维的呢。按照这个思路,我们通过递归循环遍历,把这个数组转换成为一维的数组。请看下面的代码

 1     delayering(allTreeNode, pid) { 2       allTreeNode.map(item => { 3         this.delayeringArr.push({ 4           id: item.data.id, 5           pid: pid ? pid : "null", 6           name: item.data.name 7         }); 8         if ( 9           item.hasOwnProperty("childNodes") &&10           item.childNodes.length &&11           item.expanded12         ) { // 通过检查有没有子节点,并且查看是否展开,从而确定是否递归13           this.delayering(item.childNodes, item.data.id);14         }15       });16     },

调用的时候,则需要把所有的节点的数据都传过去。

1 this.delayeringArr.splice(0);2 this.delayering([allTreeNode]); // 把现在展开的数据都扁平化

  调用delayering之后,就能把现在树结构中,已经展开的树结构,格式化成为一个一维的数组。请看下面的截图

当我们把树结构中的数据格式化成为一个一维的数组之后,我们就能判断了。那些是需要选中的。

 1     shiftTree() { 2       console.log("this.leftTreeSelectedArr", this.leftTreeSelectedArr); 3       console.log("this.delayeringArr", this.delayeringArr); 4       // 把第一个和最后一个当成是shift选择的 5       var nodeLength = this.leftTreeSelectedArr.length; 6       var startNode = this.leftTreeSelectedArr[0]; 7       var startNodeId = startNode.id; 8       var endNode = this.leftTreeSelectedArr[nodeLength - 1]; 9       var endNodeId = endNode.id;10 11       // var startIndex = this.delayeringArr.filter((item,i)=>{12       //   return itemid == startNodeId;13       // })14       // var endIndex = this.delayeringArr.filter((item,i)=>{15       //   return itemid == endNodeId;16       // })17       var startIndex, endIndex;18       this.delayeringArr.map((item, i) => {19         if (item.id == startNodeId) {20           startIndex = i;21         }22         if (item.id == endNodeId) {23           endIndex = i;24         }25       });26       if (startIndex > endIndex) {27         var rongIdex = endIndex;28         endIndex = startIndex;29         startIndex = rongIdex;30       }31       console.log(startIndex, endIndex);32       this.leftTreeSelectedArr.splice(0);33       this.delayeringArr.map((item, i) => {34         if (i >= startIndex && i <= endIndex) {35           console.log("需要选中的name", item.name);36           var node = this.$refs.treeRef.getNode(item.id);37           this.$set(node.data, "Selected", true);38           this.leftTreeSelectedArr.push(node.data);39         }40       });41       console.log("this.leftTreeSelectedArr: ", this.leftTreeSelectedArr);42     }

这个函数的主要目的就是,通过循环,找到对应的数据在扁平化处理之后数组数据中的位置。然后同理,就能找到需要选中的数据,通过设置Selected为true,则可以知道需要选中的节点。

  最后附上完成的代码, 包括其中的打印信息。(注意其中依赖Element的tree组件)

  1 <template>  2   <div id="MyVue">  3     <el-tree  4       ref="treeRef"  5       :data="treeData"  6       node-key="id"  7       :props="defaultProps"  8       @node-click="leftClick"  9     > 10        <span  slot-scope="{ node, data }"> 11          <span :>{{ node.label }}</span> 12        </span> 13     </el-tree> 14     <div>扁平化数据:{{delayeringArr}}</div> 15   </div> 16 </template> 17 <script> 18 export default { 19   name: "MyVue", 20   data() { 21     return { 22       defaultProps: { 23         children: "childrenId", 24         label: "name" 25       }, 26       treeData: [ 27         { 28           id: 1, 29           name: "1节点", 30           childrenId: [ 31             { 32               id: 2, 33               name: "2节点", 34               childrenId: [ 35                 { 36                   id: 5, 37                   name: "5节点", 38                   childrenId: [] 39                 }, 40                 { 41                   id: 6, 42                   name: "6节点", 43                   childrenId: [] 44                 } 45               ] 46             }, 47             { 48               id: 3, 49               name: "3节点", 50               childrenId: [ 51                 { 52                   id: 7, 53                   name: "7节点", 54                   childrenId: [] 55                 } 56               ] 57             }, 58             { 59               id: 4, 60               name: "4节点", 61               childrenId: [ 62                 { 63                   id: 8, 64                   name: "8节点", 65                   childrenId: [] 66                 }, 67                 { 68                   id: 9, 69                   name: "9节点", 70                   childrenId: [] 71                 }, 72                 { 73                   id: 10, 74                   name: "10节点", 75                   childrenId: [ 76                     { 77                       id: 11, 78                       name: "11节点", 79                       childrenId: [] 80                     }, 81                     { 82                       id: 12, 83                       name: "12节点", 84                       childrenId: [] 85                     } 86                   ] 87                 } 88               ] 89             } 90           ] 91         } 92       ], 93       delayeringArr: [], // 扁平化之后的数据 94       leftTreeSelectedArr: [] // 选中的数据 95     }; 96   }, 97   props: {}, 98   mounted() {}, 99   components: {},100   computed: {},101   methods: {102     leftClick(data, node, dom) {103       let event = window.event || arguments.callee.caller.arguments[0];104       var ctrlKeyDowned = event.ctrlKey;105       var shiftKeyDowned = event.shiftKey;106 107       var allTreeNode = this.$refs.treeRef.getNode(1);108       console.log("allTreeNode: ", allTreeNode);109       if (ctrlKeyDowned == false && shiftKeyDowned == false) {110         this.cancelSelectTree(); // 取消原来的选中111         this.leftTreeSelectedArr.splice(0);112         this.leftTreeSelectedArr.push(data);113       } else if (ctrlKeyDowned == true && shiftKeyDowned == false) {114         // this.leftTreeSelectedArr.splice(0);115         // data.Selected = true;116         this.$set(data, "Selected", true);117         var isIN = this.leftTreeSelectedArr.every(item => {118           return item.id != data.id;119         });120         isIN && this.leftTreeSelectedArr.push(data);121         console.log("isIN: ", isIN);122         if (!isIN) {123           // 如果已经是选中的了,那么应该取消选择124           data.Selected = false;125           this.leftTreeSelectedArr.map((item, i) => {126             if (item.id == data.id) {127               this.leftTreeSelectedArr.splice(i, 1);128               this.$refs.treeRef.setCurrentKey(); // 取消高亮,要不然区分不出来,是不是没有选中129             }130           });131         }132         console.log("this.leftTreeSelectedArr: ", this.leftTreeSelectedArr);133       } else if (ctrlKeyDowned == false && shiftKeyDowned == true) {134         this.delayeringArr.splice(0);135         this.delayering([allTreeNode]); // 把现在展开的数据都扁平化136         this.$set(data, "Selected", true);137         this.leftTreeSelectedArr.push(data);138         this.shiftTree(); // shifit多选139       }140     },141     // 把所有的数据,进行扁平化处理142     delayering(allTreeNode, pid) {143       allTreeNode.map(item => {144         this.delayeringArr.push({145           id: item.data.id,146           pid: pid ? pid : "null",147           name: item.data.name148         });149         if (150           item.hasOwnProperty("childNodes") &&151           item.childNodes.length &&152           item.expanded153         ) {154           // 通过检查有没有子节点,并且查看是否展开,从而确定是否递归155           this.delayering(item.childNodes, item.data.id);156         }157       });158     },159     shiftTree() {160       console.log("this.leftTreeSelectedArr", this.leftTreeSelectedArr);161       console.log("this.delayeringArr", this.delayeringArr);162       // 把第一个和最后一个当成是shift选择的163       var nodeLength = this.leftTreeSelectedArr.length;164       var startNode = this.leftTreeSelectedArr[0];165       var startNodeId = startNode.id;166       var endNode = this.leftTreeSelectedArr[nodeLength - 1];167       var endNodeId = endNode.id;168 169       // var startIndex = this.delayeringArr.filter((item,i)=>{170       //   return itemid == startNodeId;171       // })172       // var endIndex = this.delayeringArr.filter((item,i)=>{173       //   return itemid == endNodeId;174       // })175       var startIndex, endIndex;176       this.delayeringArr.map((item, i) => {177         if (item.id == startNodeId) {178           startIndex = i;179         }180         if (item.id == endNodeId) {181           endIndex = i;182         }183       });184       if (startIndex > endIndex) {185         var rongIdex = endIndex;186         endIndex = startIndex;187         startIndex = rongIdex;188       }189       console.log(startIndex, endIndex);190       this.leftTreeSelectedArr.splice(0);191       this.delayeringArr.map((item, i) => {192         if (i >= startIndex && i <= endIndex) {193           console.log("需要选中的name", item.name);194           var node = this.$refs.treeRef.getNode(item.id);195           this.$set(node.data, "Selected", true);196           this.leftTreeSelectedArr.push(node.data);197         }198       });199       console.log("this.leftTreeSelectedArr: ", this.leftTreeSelectedArr);200     }201   }202 };203 </script>204 <style lang="scss" scoped>205 #MyVue {206   width: 100%;207   height: 100%;208   user-select: none;209   .sel{210     color: aqua;211   }212 }213 </style>
View Code

 

posted @ 2022-05-19 14:05 程先生哈 阅读(1) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员