Svelte tooltip 更新机制:函数 vs 直接传入内容的区别?

<script>
    import tippy from 'tippy.js';

    let content = $state('Hello!');

    function tooltip(node, content) {
        $effect(() => {
            console.log(content)
            const tooltip = tippy(node, {content});

             return tooltip.destroy;
        });
    }
</script>

<input bind:value={content} />

<button use:tooltip={content}>
    Hover me
</button>

本人 svelte 小白, 这是我在实现 svelte 官网上的一个案例时,直接传入 content 给 tooltip 函数的写法

这种写法在 content 更新时, tooltip 中的内容不会更新

官方的写法是将 content 包装成函数传入, 解释如下:

We’re passing in a function, rather than the options themselves, because the tooltip function does not re-run when the options change.

为什么直接传入 content 的时候,在 content 更新时不会更新 tooltip

同时为什么使用函数时会更新呢

阅读 3.4k
avatarAI BotBETA
### 回答

在 Svelte 中,当你直接传入 `content` 给 `tooltip` 函数时,`content` 的值在组件初始化时就被捕获并传递给 `tippy` 实例。这意味着,即使后续 `content` 的值发生变化,`tippy` 实例中使用的仍然是初始化时的值。

这是因为 Svelte 的响应式系统不会自动追踪传递给非响应式函数(如这里的 `tooltip` 函数)的变量的变化。一旦这些变量被捕获并传递给函数,它们就与后续的更新解耦了。

当你将 `content` 包装成一个函数传入时,这个函数会在每次 `tooltip` 需要重新评估其依赖项时被调用。这意味着每次 `content` 的值变化时,`tippy` 实例都会接收到最新的 `content` 值。这是因为函数每次调用时都会返回当前的 `content` 值,从而允许 `tippy` 实例使用最新的内容。

简而言之:

- **直接传入 `content`**:`content` 的值在初始化时被捕获,后续变化不会反映到 `tippy` 实例中。
- **传入函数**:函数每次调用时都会返回最新的 `content` 值,因此 `tippy` 实例能够反映 `content` 的最新变化。
1 个回答

直接将content传递给tooltip函数会让tooltip的内容在content更新时不会自动更新。这是因为这传递的是一个静态值,而不是一个动态的函数。当你直接将content作为参数传入tooltip函数时,Tippy.js创建的tooltip实例只会在第一次初始化时读取这个值。之后即使content的值发生变化,tooltip实例并不会重新读取这个值,因为它没有被告知去更新。
你可以将content包装成一个函数传入。当tooltip被触发时,它会调用这个函数,从而获取最新的内容:

function tooltip(node, getContent) {
    $effect(() => {
        const tooltip = tippy(node, { content: getContent });
        return tooltip.destroy;
    });
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏