jQuery下拉组件迁移至原生JS后点击选项下拉框立即关闭问题及is/has方法原生替代方案咨询
解决下拉组件迁移到原生JS后选中选项立即关闭的问题
我明白你的问题了——原来的jQuery代码通过is()和has()判断点击事件是否来自下拉相关元素(或其子元素),如果是就阻止后续的关闭逻辑;但你写的原生JS代码只判断了点击目标是不是直接匹配选择器的元素,没考虑子元素的情况,所以点击下拉选项(子元素)的时候,就触发了关闭逻辑。
先拆解一下原jQuery代码的作用:
if($('*[data-toggle], *[data-totoggle]').is(e.target) || $('*[data-toggle], *[data-totoggle]').has(e.target).length){ return false; }
这行代码做了两件事:
- 判断点击的目标
e.target是否本身就是带有data-toggle或data-totoggle属性的元素 - 或者,点击的目标是否是这些元素的子元素(
has(e.target).length大于0意味着存在这样的父元素)
只要满足其中一个条件,就返回false,不执行后面的关闭下拉逻辑。
原生JS的等效实现
你可以用原生的closest()方法来同时覆盖这两种情况:e.target.closest('*[data-toggle], *[data-totoggle]')会返回匹配选择器的最近祖先元素(包括元素本身),如果存在这样的元素,就说明点击事件来自下拉相关元素或其子元素,此时应该阻止关闭逻辑。
修改你的mouseup事件中的判断代码:
// 替换原来的if判断 const isToggleElement = e.target.closest('*[data-toggle], *[data-totoggle]') !== null; if (isToggleElement) { return false; }
另外,你的代码里还有一些jQuery残留需要替换,避免其他潜在问题:
element.html()要改成原生的element.innerHTML或者element.textContent(如果只是操作纯文本,用后者更安全)$('*[data-toslidetoggle]').slideUp()需要用原生JS实现滑上效果,比如通过CSS过渡动画修改元素的height、opacity属性,或者先设置max-height再过渡
修改后的完整mouseup事件代码
document.addEventListener('mouseup', function (e) { // 判断点击是否来自下拉相关元素或其子元素 const isToggleElement = e.target.closest('*[data-toggle], *[data-totoggle]') !== null; if (isToggleElement) { return false; } document.querySelectorAll('*[data-toggle], *[data-totoggle]').forEach(function (element) { if (!element.classList.contains('onlyClick')) { element.classList.remove('active') } }) // 同样处理slideToggle的部分 const isSlideToggleElement = e.target.closest('*[data-slidetoggle], *[data-toslidetoggle]') !== null; if (isSlideToggleElement) { return false; } document.querySelectorAll('*[data-slidetoggle]').forEach(function (element) { if (!element.classList.contains('onlyClick')) { element.classList.remove('active'); // 替换jQuery的slideUp,这里用简单的过渡动画示例 document.querySelectorAll('*[data-toslidetoggle]').forEach(el => { el.style.transition = 'max-height 0.2s ease-out'; el.style.maxHeight = '0'; el.style.overflow = 'hidden'; }); } }) });
这样修改后,点击下拉选项(子元素)时,closest()会找到对应的父级下拉元素,从而返回false,阻止后续的关闭逻辑,下拉框就不会在选中选项后立刻关闭了。
内容的提问来源于stack exchange,提问作者niels van hoof
相关产品推荐
相关产品推荐

