You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/site/content/docs/01-component-format.md

5.4 KiB

title
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:

<script>
	// these properties can be set externally
	export let foo;
	export let bar = 'optional default value';

	// you can use export { ... as ... } to have
	// props whose names are reserved keywords
	let clazz;
	export { clazz as class };

	// this property is readonly externally
	export const buzz = 'buzz';

	// Values that are passed in as props
	// are immediately available
	console.log(foo, bar);
	
	// Function expressions can also be props
	export let format = (number) => (number.toFixed(2));

	// Function declarations are added as methods
	// on the component, rather than props
	export function greetMethod() {
		alert(`I'm a <${this.constructor.name}>!`);
	}

	// you can also use export { ... as ... } to have
	// methods whose names are reserved keywords
	function del() {
		do_something();
	}
	export { del as delete };
</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 a re-render
		// 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>

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

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.

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
</script>

<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;

	// 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>