API Docs • Svelte
source link: https://svelte.dev/docs
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Before we begin
This page contains detailed API reference documentation. It's intended to be a resource for people who already have some familiarity with Svelte.
If that's not you (yet), you may prefer to visit the interactive tutorial or the examples before consulting this reference.
Don't be shy about asking for help in the Discord chatroom.
Using an older version of Svelte? Have a look at the v2 docs.
Component format
Components are the building blocks of Svelte applications. They are written into .svelte
files, using a superset of HTML.
All three sections — script, styles and markup — are optional.
<script>
// logic goes here
</script>
<style>
/* styles go here */
</style>
<!-- markup (zero or more items) goes here -->
<script>
A <script>
block contains JavaScript that runs when a component instance is created. Variables declared (or imported) at the top level are 'visible' from the component's markup. There are four additional rules:
1. export
creates a component prop
Svelte uses the export
keyword to mark a variable declaration as a property or prop, which means it becomes accessible to consumers of the component (see the section on attributes and props for more information).
<script>
export let foo;
// Values that are passed in as props
// are immediately available
console.log({ foo });
</script>
You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is undefined
) when instantiating the component. Note that whenever a prop is removed by the consumer, its value is set to undefined
rather than the initial value.
In development mode (see the compiler options), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is undefined
.
<script>
export let bar = 'optional default initial value';
export let baz = undefined;
</script>
If you export a const
, class
or function
, it is readonly from outside the component. Function expressions are valid props, however.
<script>
// these are readonly
export const thisIs = 'readonly';
export function greet(name) {
alert(`hello ${name}!`);
}
// this is a prop
export let format = n => n.toFixed(2);
</script>
You can use reserved words as prop names.
<script>
let className;
// creates a `class` property, even
// though it is a reserved word
export { className as class };
</script>
2. Assignments are 'reactive'
To change component state and trigger a re-render, just assign to a locally declared variable.
Update expressions (count += 1
) and property assignments (obj.x = y
) have the same effect.
Because Svelte's reactivity is based on assignments, using array methods like .push()
and .splice()
won't automatically trigger updates. Options for getting around this can be found in the tutorial.
<script>
let count = 0;
function handleClick () {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
3. $:
marks a statement as reactive
Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the $:
JS label syntax. Reactive statements run immediately before the component updates, whenever the values that they depend on have changed.
<script>
export let title;
// this will update `document.title` whenever
// the `title` prop changes
$: document.title = title;
$: {
console.log(`multiple statements can be combined`);
console.log(`the current title is ${title}`);
}
</script>
Only values which directly appear within the $:
block will become dependencies of the reactive statement. For example, in the code below total
will only update when x
changes, but not y
.
<script>
let x = 0;
let y = 0;
function yPlusAValue(value) {
return value + y;
}
$: total = yPlusAValue(x);
</script>
Total: {total}
<button on:click={() => x++}>
Increment X
</button>
<button on:click={() => y++}>
Increment Y
</button>
If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a let
declaration on your behalf.
<script>
export let num;
// we don't need to declare `squared` and `cubed`
// — Svelte does it for us
$: squared = num * num;
$: cubed = squared * num;
</script>
4. Prefix stores with $
to access their values
A store is an object that allows reactive access to a value via a simple store contract. The svelte/store
module contains minimal store implementations which fulfil this contract.
Any time you have a reference to a store, you can access its value inside a component by prefixing it with the $
character. This causes Svelte to declare the prefixed variable, and set up a store subscription that will be unsubscribed when appropriate.
Assignments to $
-prefixed variables require that the variable be a writable store, and will result in a call to the store's .set
method.
Note that the store must be declared at the top level of the component — not inside an if
block or a function, for example.
Local variables (that do not represent store values) must not have a $
prefix.
<script>
import { writable } from 'svelte/store';
const count = writable(0);
console.log($count); // logs 0
count.set(1);
console.log($count); // logs 1
$count = 2;
console.log($count); // logs 2
</script>
Store contract
store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void }
You can create your own stores without relying on svelte/store
, by implementing the store contract:
- A store must contain a
.subscribe
method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling.subscribe
. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. - The
.subscribe
method must return an unsubscribe function. Calling an unsubscribe function must stop its subscription, and its corresponding subscription function must not be called again by the store. - A store may optionally contain a
.set
method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a writable store.
For interoperability with RxJS Observables, the .subscribe
method is also allowed to return an object with an .unsubscribe
method, rather than return the unsubscription function directly. Note however that unless .subscribe
synchronously calls the subscription (which is not required by the Observable spec), Svelte will see the value of the store as undefined
until it does.
<script context="module">
A <script>
tag with a context="module"
attribute runs once when the module first evaluates, rather than for each component instance. Values declared in this block are accessible from a regular <script>
(and the component markup) but not vice versa.
You can export
bindings from this block, and they will become exports of the compiled module.
You cannot export default
, since the default export is the component itself.
Variables defined in
module
scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a store.
<script context="module">
let totalComponents = 0;
// this allows an importer to do e.g.
// `import Example, { alertTotal } from './Example.svelte'`
export function alertTotal() {
alert(totalComponents);
}
</script>
<script>
totalComponents += 1;
console.log(`total number of times this component has been created: ${totalComponents}`);
</script>
<style>
CSS inside a <style>
block will be scoped to that component.
This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. svelte-123xyz
).
<style>
p {
/* this will only affect <p> elements in this component */
color: burlywood;
}
</style>
To apply styles to a selector globally, use the :global(...)
modifier.
<style>
:global(body) {
/* this will apply to <body> */
margin: 0;
}
div :global(strong) {
/* this will apply to all <strong> elements, in any
component, that are inside <div> elements belonging
to this component */
color: goldenrod;
}
</style>
If you want to make @keyframes that are accessible globally, you need to prepend your keyframe names with -global-
.
The -global-
part will be removed when compiled, and the keyframe then be referenced using just my-animation-name
elsewhere in your code.
<style>
@keyframes -global-my-animation-name {...}
</style>
Template syntax
A lowercase tag, like <div>
, denotes a regular HTML element. A capitalised tag, such as <Widget>
or <Namespace.Widget>
, indicates a component.
<script>
import Widget from './Widget.svelte';
</script>
<div>
<Widget/>
</div>
Attributes and props
By default, attributes work exactly like their HTML counterparts.
<div class="foo">
<button disabled>can't touch this</button>
</div>
As in HTML, values may be unquoted.
<input type=checkbox>
Attribute values can contain JavaScript expressions.
<a href="page/{p}">page {p}</a>
Or they can be JavaScript expressions.
<button disabled={!clickable}>...</button>
Boolean attributes are included on the element if their value is truthy and excluded if it's falsy.
All other attributes are included unless their value is nullish (null
or undefined
).
<input required={false} placeholder="This input field is not required">
<div title={null}>This div has no title attribute</div>
An expression might include characters that would cause syntax highlighting to fail in regular HTML, so quoting the value is permitted. The quotes do not affect how the value is parsed:
<button disabled="{number !== 42}">...</button>
When the attribute name and value match (name={name}
), they can be replaced with {name}
.
<!-- These are equivalent -->
<button disabled={disabled}>...</button>
<button {disabled}>...</button>
By convention, values passed to components are referred to as properties or props rather than attributes, which are a feature of the DOM.
As with elements, name={name}
can be replaced with the {name}
shorthand.
<Widget foo={bar} answer={42} text="hello"/>
Spread attributes allow many attributes or properties to be passed to an element or component at once.
An element or component can have multiple spread attributes, interspersed with regular ones.
<Widget {...things}/>
$$props
references all props that are passed to a component, including ones that are not declared with export
. It is not generally recommended, as it is difficult for Svelte to optimise. But it can be useful in rare cases – for example, when you don't know at compile time what props might be passed to a component.
<Widget {...$$props}/>
$$restProps
contains only the props which are not declared with export
. It can be used to pass down other unknown attributes to an element in a component. It shares the same optimisation problems as $$props
, and is likewise not recommended.
<input {...$$restProps}>
The
value
attribute of aninput
element or its childrenoption
elements must not be set with spread attributes when usingbind:group
orbind:checked
. Svelte needs to be able to see the element'svalue
directly in the markup in these cases so that it can link it to the bound variable.
Text expressions
{expression}
Text can also contain JavaScript expressions:
<h1>Hello {name}!</h1>
<p>{a} + {b} = {a + b}.</p>
Comments
You can use HTML comments inside components.
<!-- this is a comment! -->
<h1>Hello world</h1>
Comments beginning with svelte-ignore
disable warnings for the next block of markup. Usually these are accessibility warnings; make sure that you're disabling them for a good reason.
<!-- svelte-ignore a11y-autofocus -->
<input bind:value={name} autofocus>
{#if ...}
{#if expression}...{/if}
{#if expression}...{:else if expression}...{/if}
{#if expression}...{:else}...{/if}
Content that is conditionally rendered can be wrapped in an if block.
{#if answer === 42}
<p>what was the question?</p>
{/if}
Additional conditions can be added with {:else if expression}
, optionally ending in an {:else}
clause.
{#if porridge.temperature > 100}
<p>too hot!</p>
{:else if 80 > porridge.temperature}
<p>too cold!</p>
{:else}
<p>just right!</p>
{/if}
{#each ...}
{#each expression as name}...{/each}
{#each expression as name, index}...{/each}
{#each expression as name (key)}...{/each}
{#each expression as name, index (key)}...{/each}
{#each expression as name}...{:else}...{/each}
Iterating over lists of values can be done with an each block.
<h1>Shopping list</h1>
<ul>
{#each items as item}
<li>{item.name} x {item.qty}</li>
{/each}
</ul>
You can use each blocks to iterate over any array or array-like value — that is, any object with a length
property.
An each block can also specify an index, equivalent to the second argument in an array.map(...)
callback:
{#each items as item, i}
<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}
If a key expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change.
{#each items as item (item.id)}
<li>{item.name} x {item.qty}</li>
{/each}
<!-- or with additional index value -->
{#each items as item, i (item.id)}
<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}
You can freely use destructuring and rest patterns in each blocks.
{#each items as { id, name, qty }, i (id)}
<li>{i + 1}: {name} x {qty}</li>
{/each}
{#each objects as { id, ...rest }}
<li><span>{id}</span><MyComponent {...rest}/></li>
{/each}
{#each items as [id, ...rest]}
<li><span>{id}</span><MyComponent values={rest}/></li>
{/each}
An each block can also have an {:else}
clause, which is rendered if the list is empty.
{#each todos as todo}
<p>{todo.text}</p>
{:else}
<p>No tasks today!</p>
{/each}
{#await ...}
{#await expression}...{:then name}...{:catch name}...{/await}
{#await expression}...{:then name}...{/await}
{#await expression then name}...{/await}
{#await expression catch name}...{/await}
Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected.
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled -->
<p>The value is {value}</p>
{:catch error}
<!-- promise was rejected -->
<p>Something went wrong: {error.message}</p>
{/await}
The catch
block can be omitted if you don't need to render anything when the promise rejects (or no error is possible).
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled -->
<p>The value is {value}</p>
{/await}
If you don't care about the pending state, you can also omit the initial block.
{#await promise then value}
<p>The value is {value}</p>
{/await}
If conversely you only want to show the error state, you can omit the then
block.
{#await promise catch error}
<p>The error is {error}</p>
{/await}
{#key ...}
{#key expression}...{/key}
Key blocks destroy and recreate their contents when the value of an expression changes.
This is useful if you want an element to play its transition whenever a value changes.
{#key value}
<div transition:fade>{value}</div>
{/key}
When used around components, this will cause them to be reinstantiated and reinitialised.
{#key value}
<Component />
{/key}
{@html ...}
{@html expression}
In a text expression, characters like <
and >
are escaped; however, with HTML expressions, they're not.
The expression should be valid standalone HTML — {@html "<div>"}content{@html "</div>"}
will not work, because </div>
is not valid HTML.
Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability.
<div class="blog-post">
<h1>{post.title}</h1>
{@html post.content}
</div>
{@debug ...}
{@debug}
{@debug var1, var2, ..., varN}
The {@debug ...}
tag offers an alternative to console.log(...)
. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open.
<script>
let user = {
firstname: 'Ada',
lastname: 'Lovelace'
};
</script>
{@debug user}
<h1>Hello {user.firstname}!</h1>
{@debug ...}
accepts a comma-separated list of variable names (not arbitrary expressions).
<!-- Compiles -->
{@debug user}
{@debug user1, user2, user3}
<!-- WON'T compile -->
{@debug user.firstname}
{@debug myArray[0]}
{@debug !isReady}
{@debug typeof user === 'object'}
The {@debug}
tag without any arguments will insert a debugger
statement that gets triggered when any state changes, as opposed to the specified variables.
Element directives
As well as attributes, elements can have directives, which control the element's behaviour in some way.
on:eventname
on:eventname={handler}
on:eventname|modifiers={handler}
Use the on:
directive to listen to DOM events.
<script>
let count = 0;
function handleClick(event) {
count += 1;
}
</script>
<button on:click={handleClick}>
count: {count}
</button>
Handlers can be declared inline with no performance penalty. As with attributes, directive values may be quoted for the sake of syntax highlighters.
<button on:click="{() => count += 1}">
count: {count}
</button>
Add modifiers to DOM events with the |
character.
<form on:submit|preventDefault={handleSubmit}>
<!-- the `submit` event's default is prevented,
so the page won't reload -->
</form>
The following modifiers are available:
preventDefault
— callsevent.preventDefault()
before running the handlerstopPropagation
— callsevent.stopPropagation()
, preventing the event reaching the next elementpassive
— improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)nonpassive
— explicitly setpassive: false
capture
— fires the handler during the capture phase instead of the bubbling phaseonce
— remove the handler after the first time it runsself
— only trigger handler if event.target is the element itself
Modifiers can be chained together, e.g. on:click|once|capture={...}
.
If the on:
directive is used without a value, the component will forward the event, meaning that a consumer of the component can listen for it.
<button on:click>
The component itself will emit the click event
</button>
It's possible to have multiple event listeners for the same event:
<script>
let counter = 0;
function increment() {
counter = counter + 1;
}
function track(event) {
trackEvent(event)
}
</script>
<button on:click={increment} on:click={track}>Click me!</button>
bind:property
bind:property={variable}
Data ordinarily flows down, from parent to child. The bind:
directive allows data to flow the other way, from child to parent. Most bindings are specific to particular elements.
The simplest bindings reflect the value of a property, such as input.value
.
<input bind:value={name}>
<textarea bind:value={text}></textarea>
<input type="checkbox" bind:checked={yes}>
If the name matches the value, you can use a shorthand.
<!-- These are equivalent -->
<input bind:value={value}>
<input bind:value>
Numeric input values are coerced; even though input.value
is a string as far as the DOM is concerned, Svelte will treat it as a number. If the input is empty or invalid (in the case of type="number"
), the value is undefined
.
<input type="number" bind:value={num}>
<input type="range" bind:value={num}>
On <input>
elements with type="file"
, you can use bind:files
to get the FileList
of selected files.
<label for="avatar">Upload a picture:</label>
<input
accept="image/png, image/jpeg"
bind:files
id="avatar"
name="avatar"
type="file"
/>
Binding <select>
value
A <select>
value binding corresponds to the value
property on the selected <option>
, which can be any value (not just strings, as is normally the case in the DOM).
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b}>b</option>
<option value={c}>c</option>
</select>
A <select multiple>
element behaves similarly to a checkbox group.
<select multiple bind:value={fillings}>
<option value="Rice">Rice</option>
<option value="Beans">Beans</option>
<option value="Cheese">Cheese</option>
<option value="Guac (extra)">Guac (extra)</option>
</select>
When the value of an <option>
matches its text content, the attribute can be omitted.
<select multiple bind:value={fillings}>
<option>Rice</option>
<option>Beans</option>
<option>Cheese</option>
<option>Guac (extra)</option>
</select>
Elements with the contenteditable
attribute support innerHTML
and textContent
bindings.
<div contenteditable="true" bind:innerHTML={html}></div>
Media element bindings
Media elements (<audio>
and <video>
) have their own set of bindings — six readonly ones...
duration
(readonly) — the total duration of the video, in secondsbuffered
(readonly) — an array of{start, end}
objectsplayed
(readonly) — dittoseekable
(readonly) — dittoseeking
(readonly) — booleanended
(readonly) — boolean
...and five two-way bindings:
currentTime
— the current playback time in the video, in secondsplaybackRate
— how fast or slow to play the video, where 1 is 'normal'paused
— this one should be self-explanatoryvolume
— a value between 0 and 1muted
— a boolean value wheretrue
is muted
Videos additionally have readonly videoWidth
and videoHeight
bindings.
<video
src={clip}
bind:duration
bind:buffered
bind:played
bind:seekable
bind:seeking
bind:ended
bind:currentTime
bind:playbackRate
bind:paused
bind:volume
bind:muted
bind:videoWidth
bind:videoHeight
></video>
Block-level element bindings
Block-level elements have 4 readonly bindings, measured using a technique similar to this one:
clientWidth
clientHeight
offsetWidth
offsetHeight
<div
bind:offsetWidth={width}
bind:offsetHeight={height}
>
<Chart {width} {height}/>
</div>
bind:group
bind:group={variable}
Inputs that work together can use bind:group
.
<script>
let tortilla = 'Plain';
let fillings = [];
</script>
<!-- grouped radio inputs are mutually exclusive -->
<input type="radio" bind:group={tortilla} value="Plain">
<input type="radio" bind:group={tortilla} value="Whole wheat">
<input type="radio" bind:group={tortilla} value="Spinach">
<!-- grouped checkbox inputs populate an array -->
<input type="checkbox" bind:group={fillings} value="Rice">
<input type="checkbox" bind:group={fillings} value="Beans">
<input type="checkbox" bind:group={fillings} value="Cheese">
<input type="checkbox" bind:group={fillings} value="Guac (extra)">
bind:this
bind:this={dom_node}
To get a reference to a DOM node, use bind:this
.
<script>
import { onMount } from 'svelte';
let canvasElement;
onMount(() => {
const ctx = canvasElement.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvasElement}></canvas>
class:name
class:name={value}
class:name
A class:
directive provides a shorter way of toggling a class on an element.
<!-- These are equivalent -->
<div class="{active ? 'active' : ''}">...</div>
<div class:active={active}>...</div>
<!-- Shorthand, for when name and value match -->
<div class:active>...</div>
<!-- Multiple class toggles can be included -->
<div class:active class:inactive={!active} class:isAdmin>...</div>
use:action
use:action
use:action={parameters}
action = (node: HTMLElement, parameters: any) => {
update?: (parameters: any) => void,
destroy?: () => void
}
Actions are functions that are called when an element is created. They can return an object with a destroy
method that is called after the element is unmounted:
<script>
function foo(node) {
// the node has been mounted in the DOM
return {
destroy() {
// the node has been removed from the DOM
}
};
}
</script>
<div use:foo></div>
An action can have a parameter. If the returned value has an update
method, it will be called whenever that parameter changes, immediately after Svelte has applied updates to the markup.
Don't worry about the fact that we're redeclaring the
foo
function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.
<script>
export let bar;
function foo(node, bar) {
// the node has been mounted in the DOM
return {
update(bar) {
// the value of `bar` has changed
},
destroy() {
// the node has been removed from the DOM
}
};
}
</script>
<div use:foo={bar}></div>
transition:fn
transition:fn
transition:fn={params}
transition:fn|local
transition:fn|local={params}
transition = (node: HTMLElement, params: any) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
A transition is triggered by an element entering or leaving the DOM as a result of a state change.
When a block is transitioning out, all elements inside the block, including those that do not have their own transitions, are kept in the DOM until every transition in the block has completed.
The transition:
directive indicates a bidirectional transition, which means it can be smoothly reversed while the transition is in progress.
{#if visible}
<div transition:fade>
fades in and out
</div>
{/if}
By default intro transitions will not play on first render. You can modify this behaviour by setting
intro: true
when you create a component.
Transition parameters
Like actions, transitions can have parameters.
(The double {{curlies}}
aren't a special syntax; this is an object literal inside an expression tag.)
{#if visible}
<div transition:fade="{{ duration: 2000 }}">
flies in, fades out over two seconds
</div>
{/if}
Custom transition functions
Transitions can use custom functions. If the returned object has a css
function, Svelte will create a CSS animation that plays on the element.
The t
argument passed to css
is a value between 0
and 1
after the easing
function has been applied. In transitions run from 0
to 1
, out transitions run from 1
to 0
— in other words 1
is the element's natural state, as though no transition had been applied. The u
argument is equal to 1 - t
.
The function is called repeatedly before the transition begins, with different t
and u
arguments.
<script>
import { elasticOut } from 'svelte/easing';
export let visible;
function whoosh(node, params) {
const existingTransform = getComputedStyle(node).transform.replace('none', '');
return {
delay: params.delay || 0,
duration: params.duration || 400,
easing: params.easing || elasticOut,
css: (t, u) => `transform: ${existingTransform} scale(${t})`
};
}
</script>
{#if visible}
<div in:whoosh>
whooshes in
</div>
{/if}
A custom transition function can also return a tick
function, which is called during the transition with the same t
and u
arguments.
If it's possible to use
css
instead oftick
, do so — CSS animations can run off the main thread, preventing jank on slower devices.
<script>
export let visible = false;
function typewriter(node, { speed = 50 }) {
const valid = (
node.childNodes.length === 1 &&
node.childNodes[0].nodeType === Node.TEXT_NODE
);
if (!valid) return {};
const text = node.textContent;
const duration = text.length * speed;
return {
duration,
tick: (t, u) => {
const i = ~~(text.length * t);
node.textContent = text.slice(0, i);
}
};
}
</script>
{#if visible}
<p in:typewriter="{{ speed: 20 }}">
The quick brown fox jumps over the lazy dog
</p>
{/if}
If a transition returns a function instead of a transition object, the function will be called in the next microtask. This allows multiple transitions to coordinate, making crossfade effects possible.
Transition events
An element with transitions will dispatch the following events in addition to any standard DOM events:
introstart
introend
outrostart
outroend
{#if visible}
<p
transition:fly="{{ y: 200, duration: 2000 }}"
on:introstart="{() => status = 'intro started'}"
on:outrostart="{() => status = 'outro started'}"
on:introend="{() => status = 'intro ended'}"
on:outroend="{() => status = 'outro ended'}"
>
Flies in and out
</p>
{/if}
Local transitions only play when the block they belong to is created or destroyed, not when parent blocks are created or destroyed.
{#if x}
{#if y}
<p transition:fade>
fades in and out when x or y change
</p>
<p transition:fade|local>
fades in and out only when y changes
</p>
{/if}
{/if}
in:fn/out:fn
in:fn
in:fn={params}
in:fn|local
in:fn|local={params}
out:fn
out:fn={params}
out:fn|local
out:fn|local={params}
Similar to transition:
, but only applies to elements entering (in:
) or leaving (out:
) the DOM.
Unlike with transition:
, transitions applied with in:
and out:
are not bidirectional — an in transition will continue to 'play' alongside the out transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch.
{#if visible}
<div in:fly out:fade>
flies in, fades out
</div>
{/if}
animate:fn
animate:name
animate:name={params}
animation = (node: HTMLElement, { from: DOMRect, to: DOMRect } , params: any) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
DOMRect {
bottom: number,
height: number,
left: number,
right: number,
top: number,
width: number,
x: number,
y: number
}
An animation is triggered when the contents of a keyed each block are re-ordered. Animations do not run when an element is removed, only when the each block's data is reordered. Animate directives must be on an element that is an immediate child of a keyed each block.
Animations can be used with Svelte's built-in animation functions or custom animation functions.
<!-- When `list` is reordered the animation will run-->
{#each list as item, index (item)}
<li animate:flip>{item}</li>
{/each}
Animation Parameters
As with actions and transitions, animations can have parameters.
(The double {{curlies}}
aren't a special syntax; this is an object literal inside an expression tag.)
{#each list as item, index (item)}
<li animate:flip="{{ delay: 500 }}">{item}</li>
{/each}
Custom animation functions
Animations can use custom functions that provide the node
, an animation
object and any paramaters
as arguments. The animation
parameter is an object containing from
and to
properties each containing a DOMRect describing the geometry of the element in its start
and end
positions. The from
property is the DOMRect of the element in its starting position, the to
property is the DOMRect of the element in its final position after the list has been reordered and the DOM updated.
If the returned object has a css
method, Svelte will create a CSS animation that plays on the element.
The t
argument passed to css
is a value that goes from 0
and 1
after the easing
function has been applied. The u
argument is equal to 1 - t
.
The function is called repeatedly before the animation begins, with different t
and u
arguments.
<script>
import { cubicOut } from 'svelte/easing';
function whizz(node, { from, to }, params) {
const dx = from.left - to.left;
const dy = from.top - to.top;
const d = Math.sqrt(dx * dx + dy * dy);
return {
delay: 0,
duration: Math.sqrt(d) * 120,
easing: cubicOut,
css: (t, u) =>
`transform: translate(${u * dx}px, ${u * dy}px) rotate(${t*360}deg);`
};
}
</script>
{#each list as item, index (item)}
<div animate:whizz>{item}</div>
{/each}
A custom animation function can also return a tick
function, which is called during the animation with the same t
and u
arguments.
If it's possible to use
css
instead oftick
, do so — CSS animations can run off the main thread, preventing jank on slower devices.
<script>
import { cubicOut } from 'svelte/easing';
function whizz(node, { from, to }, params) {
const dx = from.left - to.left;
const dy = from.top - to.top;
const d = Math.sqrt(dx * dx + dy * dy);
return {
delay: 0,
duration: Math.sqrt(d) * 120,
easing: cubicOut,
tick: (t, u) =>
Object.assign(node.style, {
color: t > 0.5 ? 'Pink' : 'Blue'
});
};
}
</script>
{#each list as item, index (item)}
<div animate:whizz>{item}</div>
{/each}
Component directives
on:eventname
on:eventname={handler}
Components can emit events using createEventDispatcher, or by forwarding DOM events. Listening for component events looks the same as listening for DOM events:
<SomeComponent on:whatever={handler}/>
As with DOM events, if the on:
directive is used without a value, the component will forward the event, meaning that a consumer of the component can listen for it.
<SomeComponent on:whatever/>
bind:property
bind:property={variable}
You can bind to component props using the same syntax as for elements.
<Keypad bind:value={pin}/>
bind:this
bind:this={component_instance}
Components also support bind:this
, allowing you to interact with component instances programmatically.
Note that we can't do
{cart.empty}
sincecart
isundefined
when the button is first rendered and throws an error.
<ShoppingCart bind:this={cart}/>
<button on:click={() => cart.empty()}>
Empty shopping cart
</button>
<slot>
<slot><!-- optional fallback --></slot>
<slot name="x"><!-- optional fallback --></slot>
<slot prop={value}></slot>
Components can have child content, in the same way that elements can.
The content is exposed in the child component using the <slot>
element, which can contain fallback content that is rendered if no children are provided.
<!-- App.svelte -->
<Widget></Widget>
<Widget>
<p>this is some child content that will overwrite the default slot content</p>
</Widget>
<!-- Widget.svelte -->
<div>
<slot>
this fallback content will be rendered when no content is provided, like in the first example
</slot>
</div>
<slot name="
name">
Named slots allow consumers to target specific areas. They can also have fallback content.
<!-- App.svelte -->
<Widget>
<h1 slot="header">Hello</h1>
<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</Widget>
<!-- Widget.svelte -->
<div>
<slot name="header">No header was provided</slot>
<p>Some content between header and footer</p>
<slot name="footer"></slot>
</div>
$$slots
$$slots
is an object whose keys are the names of the slots passed into the component by the parent. If the parent does not pass in a slot with a particular name, that name will not be a present in $$slots
. This allows components to render a slot (and other elements, like wrappers for styling) only if the parent provides it.
Note that explicitly passing in an empty named slot will add that slot's name to $$slots
. For example, if a parent passes <div slot="title" />
to a child component, $$slots.title
will be truthy within the child.
<!-- App.svelte -->
<Card>
<h1 slot="title">Blog Post Title</h1>
</Card>
<!-- Card.svelte -->
<div>
<slot name="title"></slot>
{#if $$slots.description}
<!-- This slot and the <hr> before it will not render. -->
<hr>
<slot name="description"></slot>
{/if}
</div>
<slot let:
name={
value}>
Slots can be rendered zero or more times, and can pass values back to the parent using props. The parent exposes the values to the slot template using the let:
directive.
The usual shorthand rules apply — let:item
is equivalent to let:item={item}
, and <slot {item}>
is equivalent to <slot item={item}>
.
<!-- App.svelte -->
<FancyList {items} let:prop={thing}>
<div>{thing.text}</div>
</FancyList>
<!-- FancyList.svelte -->
<ul>
{#each items as item}
<li class="fancy">
<slot prop={item}></slot>
</li>
{/each}
</ul>
Named slots can also expose values. The let:
directive goes on the element with the slot
attribute.
<!-- App.svelte -->
<FancyList {items}>
<div slot="item" let:item>{item.text}</div>
<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</FancyList>
<!-- FancyList.svelte -->
<ul>
{#each items as item}
<li class="fancy">
<slot name="item" {item}></slot>
</li>
{/each}
</ul>
<slot name="footer"></slot>
<svelte:self>
The <svelte:self>
element allows a component to include itself, recursively.
It cannot appear at the top level of your markup; it must be inside an if or each block to prevent an infinite loop.
<script>
export let count;
</script>
{#if count > 0}
<p>counting down... {count}</p>
<svelte:self count="{count - 1}"/>
{:else}
<p>lift-off!</p>
{/if}
<svelte:component>
<svelte:component this={expression}/>
The <svelte:component>
element renders a component dynamically, using the component constructor specified as the this
property. When the property changes, the component is destroyed and recreated.
If this
is falsy, no component is rendered.
<svelte:component this={currentSelection.component} foo={bar}/>
<svelte:window>
<svelte:window on:event={handler}/>
<svelte:window bind:prop={value}/>
The <svelte:window>
element allows you to add event listeners to the window
object without worrying about removing them when the component is destroyed, or checking for the existence of window
when server-side rendering.
<script>
function handleKeydown(event) {
alert(`pressed the ${event.key} key`);
}
</script>
<svelte:window on:keydown={handleKeydown}/>
You can also bind to the following properties:
innerWidth
innerHeight
outerWidth
outerHeight
scrollX
scrollY
online
— an alias for window.navigator.onLine
All except scrollX
and scrollY
are readonly.
<svelte:window bind:scrollY={y}/>
<svelte:body>
<svelte:body on:event={handler}/>
As with <svelte:window>
, this element allows you to add listeners to events on document.body
, such as mouseenter
and mouseleave
which don't fire on window
.
<svelte:body
on:mouseenter={handleMouseenter}
on:mouseleave={handleMouseleave}
/>
<svelte:head>
<svelte:head>...</svelte:head>
This element makes it possible to insert elements into document.head
. During server-side rendering, head
content is exposed separately to the main html
content.
<svelte:head>
<link rel="stylesheet" href="tutorial/dark-theme.css">
</svelte:head>
<svelte:options>
<svelte:options option={value}/>
The <svelte:options>
element provides a place to specify per-component compiler options, which are detailed in the compiler section. The possible options are:
immutable={true}
— you never use mutable data, so the compiler can do simple referential equality checks to determine if values have changedimmutable={false}
— the default. Svelte will be more conservative about whether or not mutable objects have changedaccessors={true}
— adds getters and setters for the component's propsaccessors={false}
— the defaultnamespace="..."
— the namespace where this component will be used, most commonly "svg"tag="..."
— the name to use when compiling this component as a custom element
<svelte:options tag="my-custom-element"/>
Run time
svelte
The svelte
package exposes lifecycle functions and the context API.
onMount
onMount(callback: () => void)
onMount(callback: () => () => void)
The onMount
function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live inside the component; it can be called from an external module).
onMount
does not run inside a server-side component.
<script>
import { onMount } from 'svelte';
onMount(() => {
console.log('the component has mounted');
});
</script>
If a function is returned from onMount
, it will be called when the component is unmounted.
<script>
import { onMount } from 'svelte';
onMount(() => {
const interval = setInterval(() => {
console.log('beep');
}, 1000);
return () => clearInterval(interval);
});
</script>
This behaviour will only work when the function passed to
onMount
synchronously returns a value.async
functions always return aPromise
, and as such cannot synchronously return a function.
beforeUpdate
beforeUpdate(callback: () => void)
Schedules a callback to run immediately before the component is updated after any state change.
The first time the callback runs will be before the initial
onMount
<script>
import { beforeUpdate } from 'svelte';
beforeUpdate(() => {
console.log('the component is about to update');
});
</script>
afterUpdate
afterUpdate(callback: () => void)
Schedules a callback to run immediately after the component has been updated.
<script>
import { afterUpdate } from 'svelte';
afterUpdate(() => {
console.log('the component just updated');
});
</script>
onDestroy
onDestroy(callback: () => void)
Schedules a callback to run immediately before the component is unmounted.
Out of onMount
, beforeUpdate
, afterUpdate
and onDestroy
, this is the only one that runs inside a server-side component.
<script>
import { onDestroy } from 'svelte';
onDestroy(() => {
console.log('the component is being destroyed');
});
</script>
tick
promise: Promise = tick()
Returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none.
<script>
import { beforeUpdate, tick } from 'svelte';
beforeUpdate(async () => {
console.log('the component is about to update');
await tick();
console.log('the component just updated');
});
</script>
setContext
setContext(key: any, context: any)
Associates an arbitrary context
object with the current component and the specified key
. The context is then available to children of the component (including slotted content) with getContext
.
Like lifecycle functions, this must be called during component initialisation.
<script>
import { setContext } from 'svelte';
setContext('answer', 42);
</script>
Context is not inherently reactive. If you need reactive values in context then you can pass a store into context, which will be reactive.
getContext
context: any = getContext(key: any)
Retrieves the context that belongs to the closest parent component with the specified key
. Must be called during component initialisation.
<script>
import { getContext } from 'svelte';
const answer = getContext('answer');
</script>
hasContext
hasContext: boolean = hasContext(key: any)
Checks whether a given key
has been set in the context of a parent component. Must be called during component initialisation.
<script>
import { hasContext } from 'svelte';
if (hasContext('answer')) {
// do something
}
</script>
createEventDispatcher
dispatch: ((name: string, detail?: any) => void) = createEventDispatcher();
Creates an event dispatcher that can be used to dispatch component events. Event dispatchers are functions that can take two arguments: name
and detail
.
Component events created with createEventDispatcher
create a CustomEvent. These events do not bubble and are not cancellable with event.preventDefault()
. The detail
argument corresponds to the CustomEvent.detail property and can contain any type of data.
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
</script>
<button on:click="{() => dispatch('notify', 'detail value')}">Fire Event</button>
Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the detail
property of the event object.
<script>
function callbackFunction(event) {
console.log(`Notify fired! Detail: ${event.detail}`)
}
</script>
<Child on:notify="{callbackFunction}"/>
svelte/store
The svelte/store
module exports functions for creating readable, writable and derived stores.
Keep in mind that you don't have to use these functions to enjoy the reactive $store
syntax in your components. Any object that correctly implements .subscribe
, unsubscribe, and (optionally) .set
is a valid store, and will work both with the special syntax, and with Svelte's built-in derived
stores.
This makes it possible to wrap almost any other reactive state handling library for use in Svelte. Read more about the store contract to see what a correct implementation looks like.
writable
store = writable(value: any)
store = writable(value: any, (set: (value: any) => void) => () => void)
Function that creates a store which has values that can be set from 'outside' components. It gets created as an object with additional set
and update
methods.
set
is a method that takes one argument which is the value to be set. The store value gets set to the value of the argument if the store value is not already equal to it.
update
is a method that takes one argument which is a callback. The callback takes the existing store value as its argument and returns the new value to be set to the store.
import { writable } from 'svelte/store';
const count = writable(0);
count.subscribe(value => {
console.log(value);
}); // logs '0'
count.set(1); // logs '1'
count.update(n => n + 1); // logs '2'
If a function is passed as the second argument, it will be called when the number of subscribers goes from zero to one (but not from one to two, etc). That function will be passed a set
function which changes the value of the store. It must return a stop
function that is called when the subscriber count goes from one to zero.
import { writable } from 'svelte/store';
const count = writable(0, () => {
console.log('got a subscriber');
return () => console.log('no more subscribers');
});
count.set(1); // does nothing
const unsubscribe = count.subscribe(value => {
console.log(value);
}); // logs 'got a subscriber', then '1'
unsubscribe(); // logs 'no more subscribers'
readable
store = readable(value: any, (set: (value: any) => void) => () => void)
Creates a store whose value cannot be set from 'outside', the first argument is the store's initial value.
The second argument to readable
is the same as the second argument to writable
, except that it is required with readable
(since otherwise there would be no way to update the store value).
import { readable } from 'svelte/store';
const time = readable(null, set => {
set(new Date());
const interval = setInterval(() => {
set(new Date());
}, 1000);
return () => clearInterval(interval);
});
derived
store = derived(a, callback: (a: any) => any)
store = derived(a, callback: (a: any, set: (value: any) => void) => void | () => void, initial_value: any)
store = derived([a, ...b], callback: ([a: any, ...b: any[]]) => any)
store = derived([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void | () => void, initial_value: any)
Derives a store from one or more other stores. Whenever those dependencies change, the callback runs.
In the simplest version, derived
takes a single store, and the callback returns a derived value.
import { derived } from 'svelte/store';
const doubled = derived(a, $a => $a * 2);
The callback can set a value asynchronously by accepting a second argument, set
, and calling it when appropriate.
In this case, you can also pass a third argument to derived
— the initial value of the derived store before set
is first called.
import { derived } from 'svelte/store';
const delayed = derived(a, ($a, set) => {
setTimeout(() => set($a), 1000);
}, 'one moment...');
If you return a function from the callback, it will be called when a) the callback runs again, or b) the last subscriber unsubscribes.
import { derived } from 'svelte/store';
const tick = derived(frequency, ($frequency, set) => {
const interval = setInterval(() => {
set(Date.now());
}, 1000 / $frequency);
return () => {
clearInterval(interval);
};
}, 'one moment...');
In both cases, an array of arguments can be passed as the first argument instead of a single store.
import { derived } from 'svelte/store';
const summed = derived([a, b], ([$a, $b]) => $a + $b);
const delayed = derived([a, b], ([$a, $b], set) => {
setTimeout(() => set($a + $b), 1000);
});
get
value: any = get(store)
Generally, you should read the value of a store by subscribing to it and using the value as it changes over time. Occasionally, you may need to retrieve the value of a store to which you're not subscribed. get
allows you to do so.
This works by creating a subscription, reading the value, then unsubscribing. It's therefore not recommended in hot code paths.
import { get } from 'svelte/store';
const value = get(store);
svelte/motion
The svelte/motion
module exports two functions, tweened
and spring
, for creating writable stores whose values change over time after set
and update
, rather than immediately.
tweened
store = tweened(value: any, options)
Tweened stores update their values over a fixed duration. The following options are available:
delay
(number
, default 0) — milliseconds before startingduration
(number
, default 400) — milliseconds the tween lastseasing
(function
, defaultt => t
) — an easing functioninterpolate
(function
) — see below
store.set
and store.update
can accept a second options
argument that will override the options passed in upon instantiation.
Both functions return a Promise that resolves when the tween completes. If the tween is interrupted, the promise will never resolve.
Out of the box, Svelte will interpolate between two numbers, two arrays or two objects (as long as the arrays and objects are the same 'shape', and their 'leaf' properties are also numbers).
<script>
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
const size = tweened(1, {
duration: 300,
easing: cubicOut
});
function handleClick() {
// this is equivalent to size.update(n => n + 1)
$size += 1;
}
</script>
<button
on:click={handleClick}
style="transform: scale({$size}); transform-origin: 0 0"
>embiggen</button>
If the initial value is undefined
or null
, the first value change will take effect immediately. This is useful when you have tweened values that are based on props, and don't want any motion when the component first renders.
const size = tweened(undefined, {
duration: 300,
easing: cubicOut
});
$: $size = big ? 100 : 10;
The interpolate
option allows you to tween between any arbitrary values. It must be an (a, b) => t => value
function, where a
is the starting value, b
is the target value, t
is a number between 0 and 1, and value
is the result. For example, we can use the d3-interpolate package to smoothly interpolate between two colours.
<script>
import { interpolateLab } from 'd3-interpolate';
import { tweened } from 'svelte/motion';
const colors = [
'rgb(255, 62, 0)',
'rgb(64, 179, 255)',
'rgb(103, 103, 120)'
];
const color = tweened(colors[0], {
duration: 800,
interpolate: interpolateLab
});
</script>
{#each colors as c}
<button
style="background-color: {c}; color: white; border: none;"
on:click="{e => color.set(c)}"
>{c}</button>
{/each}
<h1 style="color: {$color}">{$color}</h1>
spring
store = spring(value: any, options)
A spring
store gradually changes to its target value based on its stiffness
and damping
parameters. Whereas tweened
stores change their values over a fixed duration, spring
stores change over a duration that is determined by their existing velocity, allowing for more natural-seeming motion in many situations. The following options are available:
stiffness
(number
, default0.15
) — a value between 0 and 1 where higher means a 'tighter' springdamping
(number
, default0.8
) — a value between 0 and 1 where lower means a 'springier' springprecision
(number
, default0.001
) — determines the threshold at which the spring is considered to have 'settled', where lower means more precise
As with tweened
stores, set
and update
return a Promise that resolves if the spring settles. The store.stiffness
and store.damping
properties can be changed while the spring is in motion, and will take immediate effect.
Both set
and update
can take a second argument — an object with hard
or soft
properties. { hard: true }
sets the target value immediately; { soft: n }
preserves existing momentum for n
seconds before settling. { soft: true }
is equivalent to { soft: 0.5 }
.
<script>
import { spring } from 'svelte/motion';
const coords = spring({ x: 50, y: 50 }, {
stiffness: 0.1,
damping: 0.25
});
</script>
If the initial value is undefined
or null
, the first value change will take effect immediately, just as with tweened
values (see above).
const size = spring();
$: $size = big ? 100 : 10;
svelte/transition
The svelte/transition
module exports seven functions: fade
, blur
, fly
, slide
, scale
, draw
and crossfade
. They are for use with Svelte transitions
.
fade
transition:fade={params}
in:fade={params}
out:fade={params}
Animates the opacity of an element from 0 to the current opacity for in
transitions and from the current opacity to 0 for out
transitions.
fade
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingduration
(number
, default 400) — milliseconds the transition lastseasing
(function
, defaultlinear
) — an easing function
You can see the fade
transition in action in the transition tutorial.
<script>
import { fade } from 'svelte/transition';
</script>
{#if condition}
<div transition:fade="{{delay: 250, duration: 300}}">
fades in and out
</div>
{/if}
blur
transition:blur={params}
in:blur={params}
out:blur={params}
Animates a blur
filter alongside an element's opacity.
blur
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingduration
(number
, default 400) — milliseconds the transition lastseasing
(function
, defaultcubicInOut
) — an easing functionopacity
(number
, default 0) - the opacity value to animate out to and in fromamount
(number
, default 5) - the size of the blur in pixels
<script>
import { blur } from 'svelte/transition';
</script>
{#if condition}
<div transition:blur="{{amount: 10}}">
fades in and out
</div>
{/if}
fly
transition:fly={params}
in:fly={params}
out:fly={params}
Animates the x and y positions and the opacity of an element. in
transitions animate from an element's current (default) values to the provided values, passed as parameters. out
transitions animate from the provided values to an element's default values.
fly
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingduration
(number
, default 400) — milliseconds the transition lastseasing
(function
, defaultcubicOut
) — an easing functionx
(number
, default 0) - the x offset to animate out to and in fromy
(number
, default 0) - the y offset to animate out to and in fromopacity
(number
, default 0) - the opacity value to animate out to and in from
You can see the fly
transition in action in the transition tutorial.
<script>
import { fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
{#if condition}
<div transition:fly="{{delay: 250, duration: 300, x: 100, y: 500, opacity: 0.5, easing: quintOut}}">
flies in and out
</div>
{/if}
slide
transition:slide={params}
in:slide={params}
out:slide={params}
Slides an element in and out.
slide
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingduration
(number
, default 400) — milliseconds the transition lastseasing
(function
, defaultcubicOut
) — an easing function
<script>
import { slide } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
{#if condition}
<div transition:slide="{{delay: 250, duration: 300, easing: quintOut }}">
slides in and out
</div>
{/if}
scale
transition:scale={params}
in:scale={params}
out:scale={params}
Animates the opacity and scale of an element. in
transitions animate from an element's current (default) values to the provided values, passed as parameters. out
transitions animate from the provided values to an element's default values.
scale
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingduration
(number
, default 400) — milliseconds the transition lastseasing
(function
, defaultcubicOut
) — an easing functionstart
(number
, default 0) - the scale value to animate out to and in fromopacity
(number
, default 0) - the opacity value to animate out to and in from
<script>
import { scale } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
{#if condition}
<div transition:scale="{{duration: 500, delay: 500, opacity: 0.5, start: 0.5, easing: quintOut}}">
scales in and out
</div>
{/if}
draw
transition:draw={params}
in:draw={params}
out:draw={params}
Animates the stroke of an SVG element, like a snake in a tube. in
transitions begin with the path invisible and draw the path to the screen over time. out
transitions start in a visible state and gradually erase the path. draw
only works with elements that have a getTotalLength
method, like <path>
and <polyline>
.
draw
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingspeed
(number
, default undefined) - the speed of the animation, see below.duration
(number
|function
, default 800) — milliseconds the transition lastseasing
(function
, defaultcubicInOut
) — an easing function
The speed
parameter is a means of setting the duration of the transition relative to the path's length. It is modifier that is applied to the length of the path: duration = length / speed
. A path that is 1000 pixels with a speed of 1 will have a duration of 1000ms
, setting the speed to 0.5
will double that duration and setting it to 2
will halve it.
<script>
import { draw } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
<svg viewBox="0 0 5 5" xmlns="http://www.w3.org/2000/svg">
{#if condition}
<path transition:draw="{{duration: 5000, delay: 500, easing: quintOut}}"
d="M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z"
fill="none"
stroke="cornflowerblue"
stroke-width="0.1px"
stroke-linejoin="round"
/>
{/if}
</svg>
svelte/animate
The svelte/animate
module exports one function for use with Svelte animations.
flip
animate:flip={params}
The flip
function calculates the start and end position of an element and animates between them, translating the x
and y
values. flip
stands for First, Last, Invert, Play.
flip
accepts the following parameters:
delay
(number
, default 0) — milliseconds before startingduration
(number
|function
, defaultd => Math.sqrt(d) * 120
) — see beloweasing
(function
, defaultcubicOut
) — an easing function
duration
can be be provided as either:
- a
number
, in milliseconds. - a function,
distance: number => duration: number
, receiving the distance the element will travel in pixels and returning the duration in milliseconds. This allows you to assign a duration that is relative to the distance travelled by each element.
You can see a full example on the animations tutorial
<script>
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
let list = [1, 2, 3];
</script>
{#each list as n (n)}
<div animate:flip="{{delay: 250, duration: 250, easing: quintOut}}">
{n}
</div>
{/each}
svelte/easing
Easing functions specify the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. svelte/easing
contains 31 named exports, a linear
ease and 3 variants of 10 different easing functions: in
, out
and inOut
.
You can explore the various eases using the ease visualiser in the examples section.
ease in out inOut backbackIn
backOut
backInOut
bounce
bounceIn
bounceOut
bounceInOut
circ
circIn
circOut
circInOut
cubic
cubicIn
cubicOut
cubicInOut
elastic
elasticIn
elasticOut
elasticInOut
expo
expoIn
expoOut
expoInOut
quad
quadIn
quadOut
quadInOut
quart
quartIn
quartOut
quartInOut
quint
quintIn
quintOut
quintInOut
sine
sineIn
sineOut
sineInOut
svelte/register
To render Svelte components in Node.js without bundling, use require('svelte/register')
. After that, you can use require
to include any .svelte
file.
require('svelte/register');
const App = require('./App.svelte').default;
...
const { html, css, head } = App.render({ answer: 42 });
The
.default
is necessary because we're converting from native JavaScript modules to the CommonJS modules recognised by Node. Note that if your component imports JavaScript modules, they will fail to load in Node and you will need to use a bundler instead.
To set compile options, or to use a custom file extension, call the register
hook as a function:
require('svelte/register')({
extensions: ['.customextension'], // defaults to ['.html', '.svelte']
preserveComments: true
});
Client-side component API
Creating a component
const component = new Component(options)
A client-side component — that is, a component compiled with generate: 'dom'
(or the generate
option left unspecified) is a JavaScript class.
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
// assuming App.svelte contains something like
// `export let answer`:
answer: 42
}
});
The following initialisation options can be provided:
option default descriptiontarget
none
An HTMLElement
to render to. This option is required
anchor
null
A child of target
to render the component immediately before
props
{}
An object of properties to supply to the component
hydrate
false
See below
intro
false
If true
, will play transitions on initial render, rather than waiting for subsequent state changes
Existing children of target
are left where they are.
The hydrate
option instructs Svelte to upgrade existing DOM (usually from server-side rendering) rather than creating new elements. It will only work if the component was compiled with the hydratable: true
option. Hydration of <head>
elements only works properly if the server-side rendering code was also compiled with hydratable: true
, which adds a marker to each element in the <head>
so that the component knows which elements it's responsible for removing during hydration.
Whereas children of target
are normally left alone, hydrate: true
will cause any children to be removed. For that reason, the anchor
option cannot be used alongside hydrate: true
.
The existing DOM doesn't need to match the component — Svelte will 'repair' the DOM as it goes.
import App from './App.svelte';
const app = new App({
target: document.querySelector('#server-rendered-html'),
hydrate: true
});
$set
component.$set(props)
Programmatically sets props on an instance. component.$set({ x: 1 })
is equivalent to x = 1
inside the component's <script>
block.
Calling this method schedules an update for the next microtask — the DOM is not updated synchronously.
component.$set({ answer: 42 });
$on
component.$on(event, callback)
Causes the callback
function to be called whenever the component dispatches an event
.
A function is returned that will remove the event listener when called.
const off = app.$on('selected', event => {
console.log(event.detail.selection);
});
off();
$destroy
component.$destroy()
Removes a component from the DOM and triggers any onDestroy
handlers.
Component props
component.prop
component.prop = value
If a component is compiled with accessors: true
, each instance will have getters and setters corresponding to each of the component's props. Setting a value will cause a synchronous update, rather than the default async update caused by component.$set(...)
.
By default, accessors
is false
, unless you're compiling as a custom element.
console.log(app.count);
app.count += 1;
Custom element API
Svelte components can also be compiled to custom elements (aka web components) using the customElement: true
compiler option. You should specify a tag name for the component using the <svelte:options>
element.
<svelte:options tag="my-element" />
<script>
export let name = 'world';
</script>
<h1>Hello {name}!</h1>
<slot></slot>
Alternatively, use tag={null}
to indicate that the consumer of the custom element should name it.
import MyElement from './MyElement.svelte';
customElements.define('my-element', MyElement);
Once a custom element has been defined, it can be used as a regular DOM element:
document.body.innerHTML = `
<my-element>
<p>This is some slotted content</p>
</my-element>
`;
By default, custom elements are compiled with accessors: true
, which means that any props are exposed as properties of the DOM element (as well as being readable/writable as attributes, where possible).
To prevent this, add accessors={false}
to <svelte:options>
.
const el = document.querySelector('my-element');
// get the current value of the 'name' prop
console.log(el.name);
// set a new value, updating the shadow DOM
el.name = 'everybody';
Custom elements can be a useful way to package components for consumption in a non-Svelte app, as they will work with vanilla HTML and JavaScript as well as most frameworks. There are, however, some important differences to be aware of:
- Styles are encapsulated, rather than merely scoped. This means that any non-component styles (such as you might have in a
global.css
file) will not apply to the custom element, including styles with the:global(...)
modifier - Instead of being extracted out as a separate .css file, styles are inlined into the component as a JavaScript string
- Custom elements are not generally suitable for server-side rendering, as the shadow DOM is invisible until JavaScript loads
- In Svelte, slotted content renders lazily. In the DOM, it renders eagerly. In other words, it will always be created even if the component's
<slot>
element is inside an{#if ...}
block. Similarly, including a<slot>
in an{#each ...}
block will not cause the slotted content to be rendered multiple times - The
let:
directive has no effect - Polyfills are required to support older browsers
Server-side component API
const result = Component.render(...)
Unlike client-side components, server-side components don't have a lifespan after you render them — their whole job is to create some HTML and CSS. For that reason, the API is somewhat different.
A server-side component exposes a render
method that can be called with optional props. It returns an object with head
, html
, and css
properties, where head
contains the contents of any <svelte:head>
elements encountered.
You can import a Svelte component directly into Node using svelte/register
.
require('svelte/register');
const App = require('./App.svelte').default;
const { head, html, css } = App.render({
answer: 42
});
Compile time
Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin:
Nonetheless, it's useful to understand how to use the compiler, since bundler plugins generally expose compiler options to you.
svelte.compile
result: {
js,
css,
ast,
warnings,
vars,
stats
} = svelte.compile(source: string, options?: {...})
This is where the magic happens. svelte.compile
takes your component source code, and turns it into a JavaScript module that exports a class.
const svelte = require('svelte/compiler');
const result = svelte.compile(source, {
// options
});
The following options can be passed to the compiler. None are required:
option
default
description
filename
null
string
used for debugging hints and sourcemaps. Your bundler plugin will set it automatically.
name
"Component"
string
that sets the name of the resulting JavaScript class (though the compiler will rename it if it would otherwise conflict with other variables in scope). It will normally be inferred from filename
.
format
"esm"
If "esm"
, creates a JavaScript module (with import
and export
). If "cjs"
, creates a CommonJS module (with require
and module.exports
), which is useful in some server-side rendering situations or for testing.
generate
"dom"
If "dom"
, Svelte emits a JavaScript class for mounting to the DOM. If "ssr"
, Svelte emits an object with a render
method suitable for server-side rendering. If false
, no JavaScript or CSS is returned; just metadata.
dev
false
If true
, causes extra code to be added to components that will perform runtime checks and provide debugging information during development.
immutable
false
If true
, tells the compiler that you promise not to mutate any objects. This allows it to be less conservative about checking whether values have changed.
hydratable
false
If true
when generating DOM code, enables the hydrate: true
runtime option, which allows a component to upgrade existing DOM rather than creating new DOM from scratch. When generating SSR code, this adds markers to <head>
elements so that hydration knows which to replace.
legacy
false
If true
, generates code that will work in IE9 and IE10, which don't support things like element.dataset
.
accessors
false
If true
, getters and setters will be created for the component's props. If false
, they will only be created for readonly exported values (i.e. those declared with const
, class
and function
). If compiling with customElement: true
this option defaults to true
.
customElement
false
If true
, tells the compiler to generate a custom element constructor instead of a regular Svelte component.
tag
null
A string
that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. "my-element"
.
css
true
If true
, styles will be included in the JavaScript class and injected at runtime. It's recommended that you set this to false
and use the CSS that is statically generated, as it will result in smaller JavaScript bundles and better performance.
loopGuardTimeout
0
A number
that tells Svelte to break the loop if it blocks the thread for more than loopGuardTimeout
ms. This is useful to prevent infinite loops. Only available when dev: true
preserveComments
false
If true
, your HTML comments will be preserved during server-side rendering. By default, they are stripped out.
preserveWhitespace
false
If true
, whitespace inside and between elements is kept as you typed it, rather than removed or collapsed to a single space where possible.
outputFilename
null
A string
used for your JavaScript sourcemap.
cssOutputFilename
null
A string
used for your CSS sourcemap.
sveltePath
"svelte"
The location of the svelte
package. Any imports from svelte
or svelte/[module]
will be modified accordingly.
The returned result
object contains the code for your component, along with useful bits of metadata.
const {
js,
css,
ast,
warnings,
vars,
stats
} = svelte.compile(source);
js
andcss
are objects with the following properties:code
is a JavaScript stringmap
is a sourcemap with additionaltoString()
andtoUrl()
convenience methods
ast
is an abstract syntax tree representing the structure of your component.warnings
is an array of warning objects that were generated during compilation. Each warning has several properties:code
is a string identifying the category of warningmessage
describes the issue in human-readable termsstart
andend
, if the warning relates to a specific location, are objects withline
,column
andcharacter
propertiesframe
, if applicable, is a string highlighting the offending code with line numbers
vars
is an array of the component's declarations, used by eslint-plugin-svelte3 for example. Each variable has several properties:name
is self-explanatoryexport_name
is the name the value is exported as, if it is exported (will matchname
unless you doexport...as
)injected
istrue
if the declaration is injected by Svelte, rather than in the code you wrotemodule
istrue
if the value is declared in acontext="module"
scriptmutated
istrue
if the value's properties are assigned to inside the componentreassigned
istrue
if the value is reassigned inside the componentreferenced
istrue
if the value is used in the templatereferenced_from_script
istrue
if the value is used in the<script>
outside the declarationwritable
istrue
if the value was declared withlet
orvar
(but notconst
,class
orfunction
)
stats
is an object used by the Svelte developer team for diagnosing the compiler. Avoid relying on it to stay the same!
svelte.parse
ast: object = svelte.parse(
source: string,
options?: {
filename?: string,
customElement?: boolean
}
)
The parse
function parses a component, returning only its abstract syntax tree. Unlike compiling with the generate: false
option, this will not perform any validation or other analysis of the component beyond parsing it.
const svelte = require('svelte/compiler');
const ast = svelte.parse(source, { filename: 'App.svelte' });
svelte.preprocess
A number of community-maintained preprocessing plugins are available to allow you to use Svelte with tools like TypeScript, PostCSS, SCSS, and Less.
You can write your own preprocessor using the svelte.preprocess
API.
result: {
code: string,
dependencies: Array<string>
} = await svelte.preprocess(
source: string,
preprocessors: Array<{
markup?: (input: { content: string, filename: string }) => Promise<{
code: string,
dependencies?: Array<string>
}>,
script?: (input: { content: string, attributes: Record<string, string>, filename: string }) => Promise<{
code: string,
dependencies?: Array<string>
}>,
style?: (input: { content: string, attributes: Record<string, string>, filename: string }) => Promise<{
code: string,
dependencies?: Array<string>
}>
}>,
options?: {
filename?: string
}
)
The preprocess
function provides convenient hooks for arbitrarily transforming component source code. For example, it can be used to convert a <style lang="sass">
block into vanilla CSS.
The first argument is the component source code. The second is an array of preprocessors (or a single preprocessor, if you only have one), where a preprocessor is an object with markup
, script
and style
functions, each of which is optional.
Each markup
, script
or style
function must return an object (or a Promise that resolves to an object) with a code
property, representing the transformed source code, and an optional array of dependencies
.
The markup
function receives the entire component source text, along with the component's filename
if it was specified in the third argument.
Preprocessor functions may additionally return a
map
object alongsidecode
anddependencies
, wheremap
is a sourcemap representing the transformation. In current versions of Svelte it will be ignored, but future versions of Svelte may take account of preprocessor sourcemaps.
const svelte = require('svelte/compiler');
const { code } = await svelte.preprocess(source, {
markup: ({ content, filename }) => {
return {
code: content.replace(/foo/g, 'bar')
};
}
}, {
filename: 'App.svelte'
});
The script
and style
functions receive the contents of <script>
and <style>
elements respectively. In addition to filename
, they get an object of the element's attributes.
If a dependencies
array is returned, it will be included in the result object. This is used by packages like rollup-plugin-svelte to watch additional files for changes, in the case where your <style>
tag has an @import
(for example).
const svelte = require('svelte/compiler');
const sass = require('node-sass');
const { dirname } = require('path');
const { code, dependencies } = await svelte.preprocess(source, {
style: async ({ content, attributes, filename }) => {
// only process <style lang="sass">
if (attributes.lang !== 'sass') return;
const { css, stats } = await new Promise((resolve, reject) => sass.render({
file: filename,
data: content,
includePaths: [
dirname(filename),
],
}, (err, result) => {
if (err) reject(err);
else resolve(result);
}));
return {
code: css.toString(),
dependencies: stats.includedFiles
};
}
}, {
filename: 'App.svelte'
});
Multiple preprocessors can be used together. The output of the first becomes the input to the second. markup
functions run first, then script
and style
.
const svelte = require('svelte/compiler');
const { code } = await svelte.preprocess(source, [
{
markup: () => {
console.log('this runs first');
},
script: () => {
console.log('this runs third');
},
style: () => {
console.log('this runs fifth');
}
},
{
markup: () => {
console.log('this runs second');
},
script: () => {
console.log('this runs fourth');
},
style: () => {
console.log('this runs sixth');
}
}
], {
filename: 'App.svelte'
});
svelte.walk
walk(ast: Node, {
enter(node: Node, parent: Node, prop: string, index: number)?: void,
leave(node: Node, parent: Node, prop: string, index: number)?: void
})
The walk
function provides a way to walk the abstract syntax trees generated by the parser, using the compiler's own built-in instance of estree-walker.
The walker takes an abstract syntax tree to walk and an object with two optional methods: enter
and leave
. For each node, enter
is called (if present). Then, unless this.skip()
is called during enter
, each of the children are traversed, and then leave
is called on the node.
const svelte = require('svelte/compiler');
svelte.walk(ast, {
enter(node, parent, prop, index) {
do_something(node);
if (should_skip_children(node)) {
this.skip();
}
},
leave(node, parent, prop, index) {
do_something_else(node);
}
});
svelte.VERSION
The current version, as set in package.json.
const svelte = require('svelte/compiler');
console.log(`running svelte version ${svelte.VERSION}`);
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK