Svelte Advanced Features
Explore advanced Svelte features including lifecycle, actions, special elements, and compiler optimizations:
Lifecycle Functions
<script>
import { onMount, onDestroy, beforeUpdate, afterUpdate, tick } from 'svelte';
let data;
// Runs after component first renders
onMount(async () => {
console.log('Component mounted');
const response = await fetch('/api/data');
data = await response.json();
// Return cleanup function
return () => {
console.log('Cleanup on unmount');
};
});
// Runs just before DOM updates
beforeUpdate(() => {
console.log('About to update DOM');
});
// Runs after DOM updates
afterUpdate(() => {
console.log('DOM updated');
});
// Runs when component is destroyed
onDestroy(() => {
console.log('Component destroyed');
// Cleanup subscriptions, timers, etc.
});
// Wait for pending state changes
async function updateAndFocus() {
count += 1;
await tick(); // Wait for DOM update
inputElement.focus();
}
</script>Actions
Actions are functions that are called when an element is created. They can be used to add custom behavior to elements.
<script>
// Click outside action
function clickOutside(node) {
const handleClick = (event) => {
if (!node.contains(event.target)) {
node.dispatchEvent(new CustomEvent('outclick'));
}
};
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
}
// Tooltip action with parameters
function tooltip(node, text) {
let tooltipElement;
function mouseenter() {
tooltipElement = document.createElement('div');
tooltipElement.textContent = text;
tooltipElement.className = 'tooltip';
document.body.appendChild(tooltipElement);
const rect = node.getBoundingClientRect();
tooltipElement.style.top = `${rect.bottom + 5}px`;
tooltipElement.style.left = `${rect.left}px`;
}
function mouseleave() {
if (tooltipElement) {
tooltipElement.remove();
tooltipElement = null;
}
}
node.addEventListener('mouseenter', mouseenter);
node.addEventListener('mouseleave', mouseleave);
return {
update(newText) {
text = newText;
},
destroy() {
node.removeEventListener('mouseenter', mouseenter);
node.removeEventListener('mouseleave', mouseleave);
if (tooltipElement) tooltipElement.remove();
}
};
}
let isOpen = false;
let tooltipText = 'Hover over me';
</script>
<div use:clickOutside on:outclick={() => isOpen = false}>
<button on:click={() => isOpen = true}>Open Menu</button>
{#if isOpen}
<div class="menu">Menu content</div>
{/if}
</div>
<p use:tooltip={tooltipText}>Hover for tooltip</p>Special Elements
<script>
import Component from './Component.svelte';
let currentComponent = Component;
let components = [ComponentA, ComponentB, ComponentC];
let selectedIndex = 0;
</script>
<!-- svelte:component - dynamic component -->
<svelte:component this={currentComponent} prop="value" />
<svelte:component this={components[selectedIndex]} />
<!-- svelte:self - recursive component -->
<script>
export let items = [];
</script>
{#each items as item}
<div>{item.name}</div>
{#if item.children}
<svelte:self items={item.children} />
{/if}
{/each}
<!-- svelte:window - window events -->
<svelte:window
on:keydown={(e) => console.log(e.key)}
on:resize={(e) => console.log('Resized')}
bind:scrollY={y}
bind:innerWidth={width}
/>
<!-- svelte:body - body events -->
<svelte:body on:mouseenter={handleMouseEnter} />
<!-- svelte:head - modify document head -->
<svelte:head>
<title>Page Title</title>
<meta name="description" content="Page description" />
</svelte:head>
<!-- svelte:options - compiler options -->
<svelte:options immutable={true} />
<svelte:options accessors={true} />Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free