If we only want the $-block to run on actual name
change, we can achieve that by extracting name
to a separate reactive variable. This variable will have its own "change event", independent of other object fields. In our example it's better to just define the fields as separate variables from the start, but in general this can be done using a $-variable:
const fields = {
clicks: 0,
name: ''
};
// uses primitive comparison under the hood:
$: name = fields.name
// runs on "name" change only
$: console.log(name);
<button on:click={() => fields.clicks++}>
clicks: {fields.clicks}
</button>
<input bind:value={fields.name} />
Note that object-to-object mapping does not optimize anything and just runs on every dependency change. This is because the "pure" optimization is only applied when all dependencies are primitive (computation is not triggered), or the output is primitive (further dependencies are not triggered).
If you've spent some time moving $-variables around, you know they behave weirdly from JS scoping perspective:
undefined
Here's an example to illustrate this behavior:
// you can reference variables before they're declared
$: name = state.name;
let state = {
name: ''
};
// logs "undefined"
console.log(name);
The trick is, again, simple — $-variables are just sugar over a simple let declaration and an $-block that assigns to the variable. The variable declaration is hoisted to the top (which is funny, because this perfectly emulates a var
declaration), and $-blocks become callbacks defined after the synchronous initialization code. The un-sugared equivalent of the code above will be:
// hoisted let declaration
let name;
// init block
let state = {
name: ''
};
console.log(name);
// $-blocks
$: {
name = state.name;
}
If you want to go one level down, the output in both cases is:
let name;
let state = { name: '' };
console.log(name);
$$self.$$.update = () => {
if ($$self.$$.dirty & /*state*/ 1) {
// you can reference variables before they're declared
$: name = state.name;
}
};
One funny side effect of this is that you can assign to the $-variable from e.g. another $-block, or a callback. The variable is not strongly bound to its definition, the last assignment wins. This would be quite confusing, though, and I recommend against such trickery.
To summarize, here's the result of my research:
$$invalidate(var_index, value)
call.Hope you've learnt something useful today — I sure have. Next time, we'll dissect svelte stores — follow me on twitter to stay updated!