Svelte输入框获焦后触发DOM变更意外触发blur事件的解决方案咨询
Svelte输入框获焦后触发DOM变更意外触发blur事件的解决方案咨询
嘿,我最近碰到一个头疼的问题,想跟大家请教下!
情况是这样的:当我给输入框绑定onfocus事件,在里面触发DOM变更(比如显示一个额外的元素),结果输入框的onblur事件也跟着触发了——明明视觉上输入框还处于聚焦状态,但blur事件已经执行了。这就导致我没法实现“只有输入框聚焦时才显示某个元素”的需求,因为一显示那个元素,输入框就被莫名失焦了。
举个简单的例子,代码大概是这样的:
<input onfocus={() => toggleVisibiltyOfOtherElement = true } onblur={() => console.log("blur")} />
这里的toggleVisibiltyOfOtherElement会触发DOM结构的变化,结果每次聚焦输入框,刚显示完元素,blur就打印出来了,完全不符合预期。
下面是我完整的代码示例,方便大家排查:
app.svelte
<script> import Component from "./Component.svelte" let s = $state(""); let sFilter = $state(); let showBox = $state(false); </script> <input bind:this={sFilter} type="text" bind:value={s} placeholder="search..." onfocus={() => showBox = true } onblur={() => showBox = false } /> <Component bind:visible={showBox}> box content </Component>
component.svelte
<script> import { clickoutside } from "./onclickoutside.svelte"; let { visible = $bindable(), children } = $props() </script> {#if visible} <div use:clickoutside onclickoutside={() => visible = false}> {@render children()} </div> {/if} <style> div{ position: fixed; background: pink; left: 0; top: 40px; width: 500px; height: 200px; } </style>
onclickoutside.svelte.js
export const clickoutside = (node, ignore) => { function listener(event) { const target = event.target; if (!event.target || (ignore && target.closest(ignore))) { return; } if (node && !node.contains(target) && !event.defaultPrevented) { node.dispatchEvent(new CustomEvent("clickoutside", { detail: { target } })) } } document.addEventListener("click", listener, true) return { destroy() { document.removeEventListener("click", listener, true) } } }
有没有朋友遇到过类似的问题?或者有什么解决思路可以分享下?比如有没有办法避免DOM变更触发不必要的blur事件,或者在blur事件里做判断,确保只有真正失去焦点的时候才执行对应的逻辑?
备注:内容来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

