5.0 KiB
title |
---|
Component fundamentals |
- script (module) / template / style (rough overview)
$props
/$state
(in the context of components)
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>
<!-- markup (zero or more items) goes here -->
<style>
/* styles go here */
</style>
<script>
A <script>
block contains JavaScript (or TypeScript, when adding the lang="ts"
attribute) that runs when a component instance is created. Variables declared (or imported) at the top level are 'visible' from the component's markup.
Public API of a component
Svelte uses the $props
rune to declare properties or props, which means describing the public interface of the component which becomes accessible to consumers of the component.
$props
is one of several runes, which are special hints for Svelte's compiler to make things reactive.
<script>
let { foo, bar, baz } = $props();
// Values that are passed in as props
// are immediately available
console.log({ foo, bar, baz });
</script>
You can specify a fallback value for a prop. It will be used if the component's consumer doesn't specify the prop on the component when instantiating the component, or if the passed value is undefined
at some point.
<script>
let { foo = 'optional default initial value' } = $props();
</script>
To get all properties, use rest syntax:
<script>
let { a, b, c, ...everythingElse } = $props();
</script>
You can use reserved words as prop names.
<script>
// creates a `class` property, even
// though it is a reserved word
let { class: className } = $props();
</script>
If you're using TypeScript, you can declare the prop types:
<script lang="ts">
interface Props {
required: string;
optional?: number;
[key: string]: unknown;
}
let { required, optional, ...everythingElse }: Props = $props();
</script>
If you're using JavaScript, you can declare the prop types using JSDoc:
<script>
/** @type {{ x: string }} */
let { x } = $props();
// or use @typedef if you want to document the properties:
/**
* @typedef {Object} MyProps
* @property {string} y Some documentation
*/
/** @type {MyProps} */
let { y } = $props();
</script>
If you export a const
, class
or function
, it is readonly from outside the component.
<script>
export const thisIs = 'readonly';
export function greet(name) {
alert(`hello ${name}!`);
}
</script>
Readonly props can be accessed as properties on the element, tied to the component using bind:this
syntax.
Reactive variables
To change component state and trigger a re-render, just assign to a locally declared variable that was declared using the $state
rune.
Update expressions (count += 1
) and property assignments (obj.x = y
) have the same effect.
<script>
let count = $state(0);
function handleClick() {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
Svelte's <script>
blocks are run only when the component is created, so assignments within a <script>
block are not automatically run again when a prop updates.
<script>
let { person } = $props();
// this will only set `name` on component creation
// it will not update when `person` does
let { name } = person;
</script>
If you'd like to react to changes to a prop, use the $derived
or $effect
runes instead.
<script>
let count = $state(0);
let double = $derived(count * 2);
$effect(() => {
if (count > 10) {
alert('Too high!');
}
});
</script>
For more information on reactivity, read the documentation around runes.
<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.
<script context="module">
let totalComponents = 0;
// the export keyword allows this function to imported with 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.
<style>
p {
/* this will only affect <p> elements in this component */
color: burlywood;
}
</style>
For more information regarding styling, read the documentation around styles and classes.