-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Allow transitions to be local #1734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Allows transitions to only run locally, skipping running when they are added to the DOM or removed from it. Example: ```html {#if visible} {#each things as thing} <div transition:fade|local></div> {/each} {/if} <script> export default { transitions: { fade(node, params) { return { duration: 400, css: t => { return `opacity: ${t}`; } }; } } }; </script> ``` In this example items in the each-block will fade in and fade out when they are added to or removed from `things` but the list will appear suddenly and disappear suddenly (no fade) when `visible` is toggled to `true` or `false`. This is another try at #1480.
Thanks for this. I think using pipes is a smart move. I think we can make the generated code simpler. We can avoid creating transitions at all when they're local transitions responding to non-local changes; no need to invoke So in a case like this... {#if x}
{#if y}
<div transition:foo|local>foo</div>
{/if}
{/if} ...we could generate code like this (diff from this PR): function create_main_fragment(component, ctx) {
- var if_block_anchor, current;
+ var if_block_anchor;
var if_block = (ctx.x) && create_if_block(component, ctx);
return {
c() {
if (if_block) if_block.c();
if_block_anchor = createComment();
},
- m(target, anchor, introing) {
- if (if_block) if_block.i(target, anchor, 1);
+ m(target, anchor) {
+ if (if_block) if_block.i(target, anchor);
insert(target, if_block_anchor, anchor);
- current = true;
},
p(changed, ctx) {
if (ctx.x) {
if (if_block) {
if_block.p(changed, ctx);
} else {
if_block = create_if_block(component, ctx);
if (if_block) if_block.c();
}
- if_block.i(if_block_anchor.parentNode, if_block_anchor);
+ if_block.m(if_block_anchor.parentNode, if_block_anchor);
} else if (if_block) {
- groupOutros();
- if_block.o(function() {
- if_block.d(1);
- if_block = null;
- });
+ if_block.d(1);
+ if_block = null;
}
},
-
- i(target, anchor, introing) {
- if (current) return;
-
- this.m(target, anchor, introing);
- },
-
- o(outrocallback, outroing) {
- if (!current) return;
-
- if (if_block) if_block.o(outrocallback, 1);
- else outrocallback();
-
- current = false;
- },
d(detach) {
if (if_block) if_block.d(detach);
if (detach) {
detachNode(if_block_anchor);
}
}
};
}
// (2:1) {#if y}
function create_if_block_1(component, ctx) {
var div, div_transition, current;
return {
c() {
div = createElement("div");
div.textContent = "foo";
},
- m(target, anchor, introing) {
+ m(target, anchor) {
insert(target, div, anchor);
current = true;
},
- i(target, anchor, introing) {
+ i(target, anchor) {
if (current) return;
if (component.root._intro) {
if (div_transition) div_transition.invalidate();
component.root._aftercreate.push(() => {
- if (!div_transition) div_transition = wrapTransition(component, div, foo, {}, 1, 1);
- div_transition.run(1, null, introing);
+ if (!div_transition) div_transition = wrapTransition(component, div, foo, {}, 1);
+ div_transition.run(1, null);
});
}
- this.m(target, anchor, introing);
+ this.m(target, anchor);
},
- o(outrocallback, outroing) {
+ o(outrocallback) {
if (!current) return;
- if (!div_transition) div_transition = wrapTransition(component, div, foo, {}, 0, 1);
+ if (!div_transition) div_transition = wrapTransition(component, div, foo, {}, 0);
div_transition.run(0, () => {
outrocallback();
div_transition = null;
- }, outroing);
+ });
current = false;
},
d(detach) {
if (detach) {
detachNode(div);
if (div_transition) div_transition.abort();
}
}
};
}
// (1:0) {#if x}
function create_if_block(component, ctx) {
- var if_block_anchor, current;
+ var if_block_anchor;
var if_block = (ctx.y) && create_if_block_1(component, ctx);
return {
c() {
if (if_block) if_block.c();
if_block_anchor = createComment();
},
- m(target, anchor, introing) {
- if (if_block) if_block.i(target, anchor, 1);
+ m(target, anchor) {
+ if (if_block) if_block.i(target, anchor);
insert(target, if_block_anchor, anchor);
- current = true;
},
p(changed, ctx) {
if (ctx.y) {
if (!if_block) {
if_block = create_if_block_1(component, ctx);
if_block.c();
}
if_block.i(if_block_anchor.parentNode, if_block_anchor);
} else if (if_block) {
- groupOutros();
- if_block.o(function() {
- if_block.d(1);
- if_block = null;
- });
+ if_block.d(1);
+ if_block = null;
}
},
-
- i(target, anchor, introing) {
- if (current) return;
-
- this.m(target, anchor, introing);
- },
-
- o(outrocallback, outroing) {
- if (!current) return;
-
- if (if_block) if_block.o(outrocallback, 1);
- else outrocallback();
-
- current = false;
- },
d(detach) {
if (if_block) if_block.d(detach);
if (detach) {
detachNode(if_block_anchor);
}
}
};
}
function SvelteComponent(options) {
init(this, options);
this._state = assign({}, options.data);
this._intro = !!options.intro;
this._fragment = create_main_fragment(this, this._state);
if (options.target) {
this._fragment.c();
- this._mount(options.target, options.anchor, 1);
+ this._mount(options.target, options.anchor);
flush(this);
}
this._intro = true;
} As far as I can see there's only two situations where you need to track the locality of a transition at runtime — when you're crossing a component boundary... {#if x}
{#if y}
<!-- because there's a component here, we need to track whether `y` changing
is the reason for the component's creation/destruction, in case it has a
local transition at the top-level -->
<Widget/>
{/if}
{/if} ...or when you have global transitions (or components, since they could contain global transitions) at the same level or deeper than a local transition in the same subtree: {#if x}
{#if y}
<!-- we need to generate outro code for the `x` block, but ensure
that it doesn't cause the first div's transition to run -->
<div transition:foo|local>foo</div>
<div transition:foo>foo</div>
{/if}
{/if} I made a start on this in a local branch but the further into it I get the more I think it makes sense to land #1721 first, so I'm going to spend some time on that first. |
Closing this in favour of #2008, as transitions have undergone a number of changes for v3 |
Allows transitions to only run locally, skipping running when they are added to the DOM or removed from it.
Example:
In this example items in the each-block will fade in and fade out when they are added to or removed from
things
but the list will appear suddenly and disappear suddenly (no fade) whenvisible
is toggled totrue
orfalse
.This is another try at #1480.