[Svelte] Action
Action is functions that are called when an element is created.
It is used with use: directive.
Action Function Example
<script lang="ts">
function styling(node, parameters = { width: '50px', height: '50px', color: 'tomato' }) {
const { width, height, color } = parameters;
node.style.width = width;
node.style.height = height;
node.style.backgroundColor = color;
}
</script>
<div use:styling />
<div use:styling={{ width: '100px', height: '100px', color: 'teal' }} />
styling function is called when div elements are displayed.
The node argument is the element that is declared action.
The parameters argument is the data to pass to the action.
Life Cycle of Action
function styling(node, parameters = { width: '50px', height: '50px', color: 'tomato' }) {
console.log('init');
const { width, height, color } = parameters;
node.style.width = width;
node.style.height = height;
node.style.backgroundColor = color;
return {
update(params) {
node.style.width = params.width;
},
destroy() {
console.log('destroy');
}
};
}
The function body is called when the element of action is rendered.
The destroy() function is called when the element of action is disappeared.
The update() function is called when the value of parameters is changed.
Example: Zoom In and Out
<!-- components/Action.svelte -->
<script lang="ts">
function zoom(node, parameters = 1.1) {
node.style.transition = '1s';
function zoomIn() {
node.style.transform = `scale(${parameters})`;
}
function zoomOut() {
node.style.transform = 'scale(1)';
}
node.addEventListener('mouseenter', zoomIn);
node.addEventListener('mouseleave', zoomOut);
return {
destroy() {
node.removeEventListener('mouseenter', zoomIn);
node.removeEventListener('mouseleave', zoomOut);
}
};
}
</script>
<div use:zoom />
<br />
<div use:zoom={0.7} />
<style>
div {
width: 100px;
height: 100px;
background-color: tomato;
}
</style>
When the mouse pointer enters the div area, the size of the element is scaled.
When the mouse pointer leaves the div area, the element returns to its original size.
We have already learned about it.
<script lang="ts">
import Action from '../components/Action.svelte';
</script>
<Action />
Example: Make a long press plugin
We can make things like plugins using action.
// utils/action_plugin.ts
export function longPress(node: HTMLElement, duration: number): SvelteActionReturnType {
let timer;
const handleMouseDown = () => {
timer = setTimeout(() => {
node.dispatchEvent(new CustomEvent('longPress'));
}, duration);
};
const handleMouseUp = () => {
clearTimeout(timer);
};
node.addEventListener('mousedown', handleMouseDown);
node.addEventListener('mouseup', handleMouseUp);
return {
update(newDuration) {
duration = newDuration;
},
destroy() {
node.removeEventListener('mousedown', handleMouseDown);
node.removeEventListener('mouseup', handleMouseUp);
}
};
}
We can add this action function anywhere.
<script lang="ts">
import { longPress } from '../utils/action_plugin';
let pressed = false;
let duration = 2000;
</script>
<label>
<input type="range" bind:value={duration} max={2000} step={100} />
{duration}ms
</label>
<button
use:longPress={duration}
on:longPress={() => (pressed = true)}
on:mouseenter={() => (pressed = false)}
>
Press!
</button>
{#if pressed}
<span>Clicked during {duration}ms</span>
{/if}
TaDa~!