需求:产品要求级联选择器以hover的形式展开,点击label的时候选中前面的单选框或者多选框
html代码:
第一次实现方案:利用css实现。
原理是: 把checkbox的元素层级放到最顶层,点击label的时候其实是点击到了checkbox框。
缺点: 且tooltip会收影响,因为checkbox是在最顶层了,所以鼠标上移的时候hover到的元素不是label了,就不会出现tooltip悬浮框了
核心代码:
<style>
/*cascader选中label的时候勾选前面的多选框*/
.project-cascader .el-cascader-menu .el-checkbox {
width: 100%;
height: 100%;
z-index: 10;
position: absolute;
}
.project-cascader .el-cascader-menu .el-cascader-node__label {
margin-left: 10px;
}
</style>
第二种方案:利用previousElementSibling
原理: 利用previousElementSibling拿到当前点击元素的前一个元素(也就是checkbox)然后给checkbox或radio添加点击事件
缺点: 使用setInterval会消耗性能,代码不优雅。
data() {
return {
dateTimer = 0;
}
}
beforeDestroy() {
clearInterval(this.dateTimer); // 关闭定时器
}
startTimer() {
// cascader开启多选模式下,选中label时候也能勾选前面的多选框
clearInterval(this.dateTimer);
this.dateTimer = setInterval(() => {
document.querySelectorAll('.t-el-cascader-node__label').forEach((el: any) => {
el.onclick = function () {
if (this.previousElementSibling) this.previousElementSibling.click();
};
});
}, 500);
}
第三种方案:利用previousElementSibling,是对第二种方案的优化,不使用定时器,利用点击事件去优化
看一下浏览器渲染的dom结构: 我这里是使用公司自己的组件库所以会加上前缀“t-”。
核心代码如下:
// 点击label选中前面的单选框或多选框
this.$nextTick(() => {
let d = document.getElementsByClassName('project-cascader');
for (const ele of d) {
if (ele && !(ele as any).onclick) {
(ele as any).onclick = function (e: any) {
if (e.target.parentNode.className === 't-el-cascader-node__label') { // 这里要自己改成对应的el-cascader-node__label
e.target.parentNode.previousElementSibling.click();
}
};
}
}
});