需求
项目使用element-plus的<el-trre/>,要求点击正常折叠展开,双击时执行其他逻辑。本以为在slot元素上加个@dblclick就好了,结果并不顺利。网上查了很多最后归纳实现了一个相对事件靠谱的方案。
实现
思路,利用监听用户click行为,分析是不是做的双击动作。
利用点击计数,使用防抖(debounce)控制行为流向。200毫秒内的多次点击视为双击动作(可以根据体验要求调节时间间隔)。
<template>
<el-tree
ref="_tree"
:default-expanded-keys="data.openKeys"
:props="data.tableTrreConfig"
:data="data.tableTrre"
node-key="id"
:expand-on-click-node="false"
@node-click="trreNodeClick"
>
<template #default="{ node }">
<span class="custom-tree-node">
<span>{{ node.label }}</span>
</span>
</template>
</el-tree>
</template>
<script setup>
import { watch, reactive, ref } from "vue";
const _tree = ref("");
const data = reactive({
tableTrre: [],
tableTrreConfig: {
children: "children",
label: "title",
},
openKeys: [],
});
let treeClickCount = 0;
async function trreNodeClick(d1, d2) {
treeClickCount++;
trreNodeClickListener(d1, d2);
}
function debounce(fn, awaitTime, ...args) {
let lock = null;
return function (...event) {
if (lock) clearTimeout(lock);
lock = setTimeout(() => {
fn.apply(this, [...event, ...args]);
lock = null;
}, awaitTime);
};
}
var trreNodeClickListener = debounce((...ages) => {
const [d1, d2] = ages;
if (treeClickCount > 1) {
dblclickTrre(...ages);
} else {
clickTrre(...ages);
}
treeClickCount = 0;
}, 200);
function clickTrre(d1, d2) {
const id = d1.id;
// 用来支持正常的折叠和展开
const nodesMap = _tree.value.store.nodesMap;
nodesMap[id].expanded = !nodesMap[id].expanded;
}
function dblclickTrre(d1, d2){
// 双击监听
}
<script>
<style>
// 优化双击的体验(不选择文字)
.custom-tree-node {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
</style>