mirror of https://github.com/sveltejs/svelte
fix: only re-run directly applied attachment if it changed (#15962)
* fix: only re-run directly applied attachment if it changed
* add note
* one down
* fix
* Revert "one down"
This reverts commit 9f6c4cf848
.
pull/15959/head
parent
c66a43940a
commit
93443f9316
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: only re-run directly applied attachment if it changed
|
@ -1,15 +1,33 @@
|
|||||||
import { effect } from '../../reactivity/effects.js';
|
/** @import { Effect } from '#client' */
|
||||||
|
import { block, branch, effect, destroy_effect } from '../../reactivity/effects.js';
|
||||||
|
|
||||||
|
// TODO in 6.0 or 7.0, when we remove legacy mode, we can simplify this by
|
||||||
|
// getting rid of the block/branch stuff and just letting the effect rip.
|
||||||
|
// see https://github.com/sveltejs/svelte/pull/15962
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Element} node
|
* @param {Element} node
|
||||||
* @param {() => (node: Element) => void} get_fn
|
* @param {() => (node: Element) => void} get_fn
|
||||||
*/
|
*/
|
||||||
export function attach(node, get_fn) {
|
export function attach(node, get_fn) {
|
||||||
effect(() => {
|
/** @type {false | undefined | ((node: Element) => void)} */
|
||||||
const fn = get_fn();
|
var fn = undefined;
|
||||||
|
|
||||||
|
/** @type {Effect | null} */
|
||||||
|
var e;
|
||||||
|
|
||||||
// we use `&&` rather than `?.` so that things like
|
block(() => {
|
||||||
// `{@attach DEV && something_dev_only()}` work
|
if (fn !== (fn = get_fn())) {
|
||||||
return fn && fn(node);
|
if (e) {
|
||||||
|
destroy_effect(e);
|
||||||
|
e = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn) {
|
||||||
|
e = branch(() => {
|
||||||
|
effect(() => /** @type {(node: Element) => void} */ (fn)(node));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
test({ assert, target, logs }) {
|
||||||
|
assert.deepEqual(logs, ['up']);
|
||||||
|
|
||||||
|
const button = target.querySelector('button');
|
||||||
|
|
||||||
|
flushSync(() => button?.click());
|
||||||
|
assert.deepEqual(logs, ['up']);
|
||||||
|
|
||||||
|
flushSync(() => button?.click());
|
||||||
|
assert.deepEqual(logs, ['up', 'down']);
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
<script>
|
||||||
|
let state = {
|
||||||
|
count: 0,
|
||||||
|
attachment(){
|
||||||
|
console.log('up');
|
||||||
|
return () => console.log('down');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => state.count++}>{state.count}</button>
|
||||||
|
|
||||||
|
{#if state.count < 2}
|
||||||
|
<div {@attach state.attachment}></div>
|
||||||
|
{/if}
|
Loading…
Reference in new issue