It’s still explicit, just at the
language level rather than the
library level. (Svelte components aren’t written with JavaScript, but a language that extends JavaScript, repurposing $ labels and $-prefixed identifiers. Not appreciating that Svelte is a
language and not just a library is a common cause for discomfort at the Svelte approach.)
The only part that is less explicit than some reactivity libraries is which variables’ changes will trigger re-evaluation.
Some libraries go full-explicit with the likes of foo.observe(foo => …) or computed(([foo]) => …, ["foo"]), requiring that you enumerate the properties to depend on. This is easy to get wrong, leading to bad reactivity.
Some libraries go full-implicit, tracking which properties were accessed during the call. This can be functionally perfect (provided you only use observable objects or primitive values—no Array, for example, leading to the amusing situation of some common patterns being syntactically heavier), but harder to reason about, and makes static analysis impossible in the general case, since property access can be non-local.
Svelte lies between the two extremes, needing no special syntax for it, but just noting which local variables are touched inside the block. This makes bad reactivity quite possible (non-local effects aren’t observed, including object nesting), but the language semantics of $ blocks are easy to learn, which mitigates this (though it’s still the most common sort of beginner error, when people try just using it rather than learning it). Static analysis and reasoning aren’t quite as simple as full-explicit, but are still straightforward in sanely-written code.