如何在Svelte中条件性使用use:registerFocus指令?
问题背景
编辑:之前参考的包装方法无法适用于输入框聚焦的场景。
我正在使用svelte-navigator提供的useFocus()指令,实现了一个Input组件,希望通过isFocused属性控制单个Input实例获得焦点,其他实例则不聚焦。
核心问题:如何在Svelte中条件性启用use:registerFocus?
现有代码
Input.svelte:
<script> import { useFocus } from "svelte-navigator"; const registerFocus = useFocus(); // 如何让组件仅在isFocused为true时启用use:registerFocus? export let isFocused export let value const maybeRegisterFocus = (element, isFocused) => { console.log(`为'${value}'注册焦点: ${isFocused}`) if (isFocused) { registerFocus(element); } return { update: (isFocused) => { console.log(`更新元素`, element) if (isFocused) { registerFocus(element); } return null; }, destroy: () => { return null; }, }; }; </script> <input use:maybeRegisterFocus={isFocused} value={value} />
App.svelte:
<script> import { Router, Route } from "svelte-navigator"; import Input from "./Input.svelte" </script> <Router> <Route> <h1> 第一个输入框应该被聚焦。 <Input isFocused={true} value="第一个输入框应该被聚焦"/> <Input isFocused={false} value="第二个输入框不应该被聚焦"/> </h1> </Route> </Router>
解决方案
你的包装指令没有处理useFocus返回的销毁函数,且状态切换时未清理旧的焦点注册。修改后的Input.svelte如下:
<script> import { useFocus } from "svelte-navigator"; export let isFocused; export let value; const maybeRegisterFocus = (element, shouldFocus) => { let destroyFocus = null; const updateFocus = (newShouldFocus) => { // 先清理已有的焦点注册 if (destroyFocus) { destroyFocus(); destroyFocus = null; } // 需要聚焦时注册并保存销毁函数 if (newShouldFocus) { destroyFocus = useFocus()(element); } }; // 初始化执行一次 updateFocus(shouldFocus); return { update: updateFocus, destroy: () => destroyFocus?.(), }; }; </script> <input use:maybeRegisterFocus={isFocused} {value} />
关键说明
- 状态切换清理:每次
isFocused变化时,先调用之前保存的销毁函数,取消旧的焦点绑定,避免多个实例同时注册焦点。 - 动态注册:仅当
isFocused为true时,才调用useFocus()生成指令并绑定到元素,同时保存销毁函数用于后续清理。 - 组件销毁清理:组件销毁时自动调用销毁函数,确保资源被正确释放。
内容的提问来源于stack exchange,提问作者mikemaccana
相关产品推荐
相关产品推荐

