如何解决使用 CSS/JavaScript 实现双击控件
我正在尝试实现一个双击控件,该控件在第一次单击时显示操作,并允许在可选的第二次单击时启动该操作。这部分很简单,我已经完成了(见下面的代码)。照原样,第一次点击后第一个动作被删除,第二个动作被附加。但是,如果用户不想在第一个操作后继续,我希望小部件恢复到初始状态,以便他们可以在稍后执行显示优先,第二操作的序列。我想不出一种优雅的方式来做到这一点。欢迎提出建议(甚至替代的实施方式)。
const first = (e) => {
e.stopImmediatePropagation()
e.target.removeEventListener('click',first)
e.target.addEventListener('click',second)
}
const second = (e) => {
console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`)
}
const btns = document.querySelectorAll('.semafore')
btns.forEach(b => { b.addEventListener('click',first) })
.semafores { display: block; width: auto; height: 40px; }
.r { background: red; }
.g { background: green; }
.b { background: blue; }
.semafore {
float: left;
width: 30px;
height: 30px;
border: 1px solid black;
border-radius: 15px;
display: block;
text-align: center;
font-family: sans-serif;
color: white;
transition: width 0.5s ease-in-out,color 0.2s;
}
.semafore.r:focus,.semafore.g:focus,.semafore.b:focus { width: auto; padding: 0 10px; }
.semafore.r:focus::after,.semafore.g:focus::after,.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
<button id="1r" data-val='remove' class="r semafore"></button>
<button id="1g" data-val='change' class="g semafore"></button>
<button id="1b" data-val='report' class="b semafore"></button>
</div>
<div class="semafores">
<button id="2r" data-val='remove' class="r semafore"></button>
<button id="2g" data-val='change' class="g semafore"></button>
<button id="2b" data-val='report' class="b semafore"></button>
</div>
解决方法
这样弄怎么样?我们可以用状态创建一个,而不是两个事件:
const event = (e) => {
e.stopImmediatePropagation()
var state = e.target.dataset['state']
if(state === 'first') {
e.target.dataset['state'] = 'second'
first(e)
} else {
second(e)
}
}
const first = (e) => {
console.log(`first ${e.target.getAttribute('data-val')} ${e.target.id}`)
}
const second = (e) => {
console.log(`second ${e.target.getAttribute('data-val')} ${e.target.id}`)
}
const btns = document.querySelectorAll('.semafore')
btns.forEach(b => { b.addEventListener('click',event) })
.semafores { display: block; width: auto; height: 40px; }
.r { background: red; }
.g { background: green; }
.b { background: blue; }
.semafore {
float: left;
width: 30px;
height: 30px;
border: 1px solid black;
border-radius: 15px;
display: block;
text-align: center;
font-family: sans-serif;
color: white;
transition: width 0.5s ease-in-out,color 0.2s;
}
.semafore.r:focus,.semafore.g:focus,.semafore.b:focus { width: auto; padding: 0 10px; }
.semafore.r:focus::after,.semafore.g:focus::after,.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
<button id="1r" data-state="first" data-val='remove' class="r semafore"></button>
<button id="1g" data-state="first" data-val='change' class="g semafore"></button>
<button id="1b" data-state="first" data-val='report' class="b semafore"></button>
</div>
<div class="semafores">
<button id="2r" data-state="first" data-val='remove' class="r semafore"></button>
<button id="2g" data-state="first" data-val='change' class="g semafore"></button>
<button id="2b" data-state="first" data-val='report' class="b semafore"></button>
</div>
您可以使用 reset()
函数。
使用两个不同的事件侦听器:
(就像你的例子)
const reset = () => {
btns.forEach(btn => {
btn.removeEventListener('click',second);
btn.addEventListener('click',first);
});
};
您可以在更改 first()
中的事件侦听器之前或在 console.log()
中的 second()
之前调用它,
const first = (e) => {
e.stopImmediatePropagation();
reset();
e.target.removeEventListener('click',first);
e.target.addEventListener('click',second);
};
const second = (e) => {
e.stopImmediatePropagation();
reset();
console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
};
或者如果您在 button.semafore
之外点击。
document.addEventListener('click',reset);
工作示例:
const btns = document.querySelectorAll('.semafore');
const reset = () => {
btns.forEach(btn => {
btn.removeEventListener('click',first);
});
};
const first = (e) => {
e.stopImmediatePropagation();
reset();
e.target.removeEventListener('click',second);
};
const second = (e) => {
e.stopImmediatePropagation();
reset();
console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
};
btns.forEach(b => { b.addEventListener('click',first); });
document.addEventListener('click',reset);
.semafores { display: block; width: auto; height: 40px; }
.r { background: red; }
.g { background: green; }
.b { background: blue; }
.semafore {
float: left;
width: 30px;
height: 30px;
border: 1px solid black;
border-radius: 15px;
display: block;
text-align: center;
font-family: sans-serif;
color: white;
transition: width 0.5s ease-in-out,color 0.2s;
}
.semafore.r:focus,.semafore.b:focus { width: auto; padding: 0 10px; }
.semafore.r:focus::after,.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
<button id="1r" data-val='remove' class="r semafore"></button>
<button id="1g" data-val='change' class="g semafore"></button>
<button id="1b" data-val='report' class="b semafore"></button>
</div>
<div class="semafores">
<button id="2r" data-val='remove' class="r semafore"></button>
<button id="2g" data-val='change' class="g semafore"></button>
<button id="2b" data-val='report' class="b semafore"></button>
</div>
有数据属性:
const reset = () => {
const active_btn = document.querySelector('[data-active="true"]');
if (active_btn) {
active_btn.dataset.active = 'false';
}
};
您可以在一个处理程序中处理两次点击:
const handleClick = (e) => {
e.stopImmediatePropagation();
if (e.target.dataset.active == 'true') {
reset();
console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
}
else {
reset();
e.target.dataset.active = 'true';
}
};
工作示例:
const btns = document.querySelectorAll('.semafore');
const reset = () => {
const active_btn = document.querySelector('[data-active="true"]');
if (active_btn) {
active_btn.dataset.active = 'false';
}
};
const handleClick = (e) => {
e.stopImmediatePropagation();
if (e.target.dataset.active == 'true') {
reset();
console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
}
else {
reset();
e.target.dataset.active = 'true';
}
};
btns.forEach(b => { b.addEventListener('click',handleClick); });
document.addEventListener('click',.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
<button id="1r" data-val='remove' data-active="false" class="r semafore"></button>
<button id="1g" data-val='change' data-active="false" class="g semafore"></button>
<button id="1b" data-val='report' data-active="false" class="b semafore"></button>
</div>
<div class="semafores">
<button id="2r" data-val='remove' data-active="false" class="r semafore"></button>
<button id="2g" data-val='change' data-active="false" class="g semafore"></button>
<button id="2b" data-val='report' data-active="false" class="b semafore"></button>
</div>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。