一、看效果:
按住ctrl鍵實現單個多選? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 按住shift實現區間范圍多選? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ??
二、代碼:
????????vue頁面
<template><el-treeclass="w100%":data="$.treeData"ref="treeTableListRef":props="$.defaultProps"highlight-current:expand-on-click-node="false"key="id":default-expand-all="true"@node-click="(data, node) => $.tableFieldsNodeClick(data, node, treeTableListRef)"><template #default="{ data }"><div style="user-select: none">{{ data.name }}</div></template></el-tree>
</template><script setup lang="ts">
import { useData } from "./hooks/index";
const treeTableListRef = ref();
let { $data: $ } = useData();
onMounted(() => {});
onBeforeMount(() => {window.addEventListener("keydown", handleKeyDown);window.addEventListener("keyup", handleKeyUp);
});
// 按下為true
const handleKeyDown = (event: any) => {// 代表按下的是ctrl鍵if (event.key == "Control") {$.ctrlKeyPressed = true;}// 代表按下的是shift鍵if (event.key == "Shift") {$.shiftKeyPressed = true;}
};
// 釋放為false
const handleKeyUp = (event: any) => {// 代表按下的是ctrl鍵if (event.key == "Control") {$.ctrlKeyPressed = false;}// 代表按下的是shift鍵if (event.key == "Shift") {$.shiftKeyPressed = false;}
};
</script><style scoped lang="scss">
</style>
????????引入的hooks文件,index.ts
export function useData() {const $data: any = reactive({ctrlKeyPressed: false,shiftKeyPressed: false,shiftKeyFelid: [],defaultProps: {children: "children",label: "name",},treeData: [{name: '一級1',id: 1,children: [{name: '二級1',id: 2,children: [{name: '三級1',id: 2,}, {name: '三級2',id: 3,}, {name: '三級3',id: 4,}, {name: '三級4',id: 5,}, {name: '三級5',id: 6,}]}, {name: '二級2',id: 3,}, {name: '二級3',id: 4,}, {name: '二級4',id: 5,}, {name: '二級5',id: 6,}]}, {name: '一級2',id: 7,children: [{name: '二級1',id: 8,}, {name: '二級2',id: 9,}, {name: '二級3',id: 10,}, {name: '二級4',id: 11,}, {name: '二級5',id: 12,}]}],selectNodes: []})// 節點選中事件$data.tableFieldsNodeClick = (nodeData: any, node: any, treeTableListRef: any) => {const nodes = treeTableListRef.store._getAllNodes();//所有node節點const ishas = $data.selectNodes.includes(node.id)// 遞歸遍歷節點數組進行ID存放function addSelectId(arr: any) {for (const item of arr) {$data.selectNodes.push(item.id)if (Array.isArray(item.children) && item.children.length) {addSelectId(item.children)}}}// 遞歸遍歷刪除節點idfunction delSelectId(arr: any) {for (const item of arr) {const index = $data.selectNodes.findIndex((x: any) => x == item.id);$data.selectNodes.splice(index, 1);if (Array.isArray(item.children) && item.children.length) {delSelectId(item.children);}}}// 按住了ctrl鍵,可以進行單個多選if ($data.ctrlKeyPressed) {// 如果為true代表當前選中的節點已存在if (ishas) {// 查找當前選中的節點的索引const index = $data.selectNodes.findIndex((x: any) => x == node.id);// 刪除父節點$data.selectNodes.splice(index, 1);// 刪除子節點if (Array.isArray(node.childNodes) && node.childNodes.length) {deleteSelectId(node.childNodes);}} else {// 否則當前選中的節點不存在,就加入到已選節點數組序列$data.selectNodes.push(node.id)// 防止選中的是父節點,就需要遞歸將子節點加入if (Array.isArray(node.childNodes) && node.childNodes.length) {addSelectId(node.childNodes);}}node.isCurrent = !node.isCurrent;// 按下了shift鍵,可以進行范圍多選} else if ($data.shiftKeyPressed) {// 先清空$data.selectNodes = []// 將當前節點放入$data.selectNodes.push(node.id)$data.shiftKeyFelid.push(node.id);if ($data.shiftKeyFelid.length > 1) {// 首索引const sIndex = nodes.findIndex((x: any) => x.id == $data.shiftKeyFelid[0])// 尾索引const eIndex = nodes.findIndex((x: any) => x.id == $data.shiftKeyFelid[$data.shiftKeyFelid.length - 1]);// 根據首尾索引,存入中間節點const s = sIndex < eIndex ? sIndex : eIndex //取小值當開頭索引const e = sIndex < eIndex ? eIndex : sIndex//取大值當結尾索引for (let i = s; i < e; i++) {// 放入該區間節點id$data.selectNodes.push(nodes[i].id);}}} else {// 否則就是單機選擇$data.shiftKeyFelid = [];$data.selectNodes = [];$data.selectNodes = [node.id];}// 下面是對已選中的節點,進行高亮展示// 通過控制elementui中節點上的isCurrent屬性// isCurrent為true是高亮,否則取消高亮for (const item of nodes) {if ($data.selectNodes.includes(item.id)) {item.isCurrent = true;} else {item.isCurrent = false;}}};return {$data: $data}
}
三、注意:
? ? ? ? 1、重點是要獲取當前所選節點數組
????????2、通過循環節點數組來更新nodes節點中isCurrent屬性,控制高亮