如何在 Svelte 3 中有条件地添加和删除 `use:` 属性?

How to conditional add and remove `use:` property in Svelte 3?

有没有办法在 Svelte 3 中优雅地有条件地添加和删除 use: 属性?

示例:

<script>
    import {classes} from "./functions.js"

    export let originalClasses
</script>

<button use:classes>Button</button>

如果 originalClasses 为真,是否可以添加或删除 use:classes

Svelte 中的动作可以接收一个参数,您可以使用该参数来启用或禁用效果:

https://svelte.dev/docs#use_action

这是你想要做的吗?

REPL

//functions.js
export default function classes(node,options){
    if(options){
    node.className="myClass";
    }
        console.log(node);
}

鉴于您无法控制 classes 函数,一种方法是用您自己的函数包装操作:

import classes from '....'
function classesWrap(node, useDefault = true) {
  useDefault && classes(node);
  
  return {
    update(useDefault) {
      useDefault && classes(node);
    }
  }
}

然后改用此操作:<div use:classesWrap={originalClasses}>

这有点像,当 originalClasses 为 false 时,它​​不会设置默认值,当它为 true 时,它​​会设置它们。当它开始为 false 并变为 true 时,它​​也会应用它们(感谢 update但是 似乎一旦附加了一个动作就无法再次删除(这是合乎逻辑,因为当元素被挂载时,操作应该 运行)。这意味着从 true 变为 false 不会改变任何东西,它会保持默认 类.

有两种(非常糟糕的)解决方法:

  1. 在更新函数中添加一些额外的代码来自己删除 类:
update(useDefault) {
  useDefault && classes(node);
  !useDefault && node.classList.remove(...node.classList);
}

(但这会删除 所有 类,还有您可能自己添加的那些)

  1. 第二个选项是根据 originalClasses{#key} 块包裹元素,这将在元素发生变化时强制重新渲染。
{#key originalClasses}
 <div use:classesWrap={originalClasses}>...</div>
{/key}

但是如果这个 div 有很多内容,这可能会 非常 昂贵,也许对于一行元素可能没问题。

(注意:您不再需要 update 函数)

当然,这假设 originalClasses 可以而且将会改变,如果您 100% 确定它将 永远不会 改变,只需使用包装器而不更新或密钥块。