개발 공부/Svelte

Svelte) Element directives

Ryomi 2023. 9. 18. 17:38
728x90
반응형

 

 

- on: eventName

on:eventname={handler}

on:eventname|modifiers={handler}

: on: 지시문을 사용하여 DOM 이벤트를 수신

<script>
	let count = 0;

	/** @param {MouseEvent} event */
	function handleClick(event) {
		count += 1;
	}
</script>

<button on:click={handleClick}>
	count: {count}
</button>

 

: 핸들러는 인라인으로 선언할 수 있으며, 성능 저하가 없다. 속성과 마찬가지로, 구문 하이라이터를 위해 디렉티브 값에 따옴표를 사용할 수 있다.

<button on:click={() => (count += 1)}>
	카운트: {count}
</button>


: '|' 문자로 DOM 이벤트에 수정자를 추가할 수 있다.

<form on:submit|preventDefault={handleSubmit}>
	<!-- the `submit` event's default is prevented, so the page won't reload -->
</form>

 

 

: 사용할 수 있는 Modifiers

preventDefault — 핸들러를 실행하기 전에 event.preventDefault()를 호출
stopPropagation — event.stopPropagation()를 호출하여 이벤트가 다음 요소에 도달하는 것을 방지
stopImmediatePropagation - event.stopImmediatePropagation()를 호출하여 같은 이벤트의 다른 리스너가 실행되는 것을 방지
passive — 터치/휠 이벤트의 스크롤 성능을 향상시킴(Svelte는 안전하게 사용할 수 있는 곳에서 자동으로 추가).
nonpassive — 명시적으로 passive: false를 설정
capture — 버블링 단계 대신 캡처 단계에서 핸들러를 실행시킴
once — 핸들러가 처음 실행된 후에 핸들러를 제거
self — event.target이 요소 자체인 경우에만 핸들러를 트리거
trusted — event.isTrusted가 참인 경우에만 핸들러를 트리거. 즉, 이벤트가 사용자 액션에 의해 트리거된 경우.
수정자는 체인으로 연결할 수 있음. (예: on:click|once|capture={...})


: on: 지시문이 값 없이 사용되면, 컴포넌트는 이벤트를 전달하며, 이는 컴포넌트의 소비자가 이를 수신할 수 있음을 의미

<button on:click> The component itself will emit the click event </button>

 

: 같은 이벤트에 대해 여러 이벤트 리스너를 가질 수 있음

<script>
	let counter = 0;
	function increment() {
		counter = counter + 1;
	}

	/** @param {MouseEvent} event */
	function track(event) {
		trackEvent(event);
	}
</script>

<button on:click={increment} on:click={track}>Click me!</button>

 

 

- bind:property

: 데이터는 일반적으로 부모에서 자식으로 흐른다. 'bind:' 지시문을 사용하면 데이터를 자식에서 부모로 흐르게 할 수 있다. 대부분의 바인딩은 특정 요소에 특화되어 있다.

: 가장 간단한 바인딩은 속성의 값을 반영하는 것으로, input.value와 같은 경우이다.

<input bind:value={name} />
<textarea bind:value={text} />

<input type="checkbox" bind:checked={yes} />

 

: 이름이 값과 일치하면, 단축형을 사용할 수 있다.

<input bind:value />
<!-- equivalent to <input bind:value={value} /> -->



: 숫자 입력 값은 강제 변환된다. DOM에서 input.value는 문자열로 취급되지만, Svelte에서는 숫자로 취급한다. 입력이 비어 있거나 유효하지 않은 경우(예: type="number"), 값은 undefined이다.

<input type="number" bind:value={num} />
<input type="range" bind:value={num} />

 

: type="file"인 <input> 요소에서는 bind:files를 사용하여 선택된 파일의 FileList를 얻을 수 있다. 이는 읽기 전용이다.

<label for="avatar">Upload a picture:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />

 

 

: bind: 지시문과 on: 지시문을 함께 사용하는 경우, 이들이 정의된 순서에 따라 이벤트 핸들러가 호출될 때 바인딩 변수의 값이 영향을 받는다.

<script>
	let value = 'Hello World';
</script>

<input
	on:input={() => console.log('Old value:', value)}
	bind:value
	on:input={() => console.log('New value:', value)}
/>

 

여기서는 input 이벤트를 사용하는 텍스트 입력의 값을 바인딩했다. 다른 요소에서의 바인딩은 change와 같은 다른 이벤트를 사용할 수 있다.

 

Binding <select> value

: <select> 값 바인딩은 선택된 <option>의 value 속성에 해당하며, 이는 어떤 값이든 될 수 있습니다(DOM에서 일반적으로 문자열만 가능).

<select bind:value={selected}>
	<option value={a}>a</option>
	<option value={b}>b</option>
	<option value={c}>c</option>
</select>

 

: <select multiple> 요소는 체크박스 그룹과 비슷하게 동작합니다. 바인딩 변수는 선택된 각 <option>의 value 속성에 해당하는 항목이 있는 배열입니다.

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

 

: <option>의 값이 텍스트 내용과 일치하면, 속성을 생략할 수 있습니다.

<select multiple bind:value={fillings}>
	<option>Rice</option>
	<option>Beans</option>
	<option>Cheese</option>
	<option>Guac (extra)</option>
</select>

 

: contenteditable 속성을 가진 요소는 innerHTML, innerText, textContent 바인딩을 지원합니다:

: 각각에는 약간의 차이가 있으며, 여기에서 더 자세히 읽을 수 있습니다.

<div contenteditable="true" bind:innerHTML={html} />

 

: details 요소는 open 속성에 바인딩할 수 있습니다.

<details bind:open={isOpen}>
	<summary>Details</summary>
	<p>Something small enough to escape casual notice.</p>
</details>

 

 

Media element bindings

: 미디어 요소(<audio> 및 <video>)는 다음과 같은 바인딩을 가지고 있습니다.

duration (읽기 전용) - 비디오의 총 재생 시간(초)
buffered (읽기 전용) - {start, end} 객체의 배열
played (읽기 전용) - 위와 동일
seekable (읽기 전용) - 위와 동일
seeking (읽기 전용) - 불리언 값
ended (읽기 전용) - 불리언 값
readyState (읽기 전용) - 0에서 4 사이(포함)의 숫자
currentTime - 비디오의 현재 재생 시간(초)
playbackRate - 비디오를 재생하는 속도, 1은 '보통'을 의미함
paused - 이것은 자명한 것이어야 함
volume - 0과 1 사이의 값
muted - 플레이어가 음소거되었는지를 나타내는 불리언 값

비디오는 또한 읽기 전용의 videoWidth 및 videoHeight 바인딩을 가지고 있습니다.

<video
	src={clip}
	bind:duration
	bind:buffered
	bind:played
	bind:seekable
	bind:seeking
	bind:ended
	bind:readyState
	bind:currentTime
	bind:playbackRate
	bind:paused
	bind:volume
	bind:muted
	bind:videoWidth
	bind:videoHeight
/>

 

 

- Image element bindings

: 이미지 요소(<img>)는 두 개의 읽기 전용 바인딩을 가지고 있습니다:

: naturalWidth (읽기 전용) - 이미지의 원래 너비, 이미지가 로드된 후 사용 가능

<img
	bind:naturalWidth
	bind:naturalHeight
/>

 

 

Block-level element bindings

: 블록 수준 요소는 이와 유사한 기술을 사용하여 측정된 4개의 읽기 전용 바인딩을 가지고 있습니다:

clientWidth
clientHeight
offsetWidth
offsetHeight
<div bind:offsetWidth={width} bind:offsetHeight={height}>
	<Chart {width} {height} />
</div>

 

 

- bind:group

: 함께 작동하는 입력은 bind:group을 사용할 수 있습니다.

<script>
	let tortilla = 'Plain';

	/** @type {Array<string>} */
	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:group은 입력이 동일한 Svelte 컴포넌트에 있어야만 작동합니다.

 

 

- bind:this

: DOM 노드에 대한 참조를 얻으려면 bind:this를 사용하세요.

<script>
	import { onMount } from 'svelte';

	/** @type {HTMLCanvasElement} */
	let canvasElement;

	onMount(() => {
		const ctx = canvasElement.getContext('2d');
		drawStuff(ctx);
	});
</script>

<canvas bind:this={canvasElement} />

 



- class:name

: class: 지시문은 요소에 클래스를 토글하는 더 짧은 방법을 제공합니다.

<script>
  let isActive = true;
</script>

<style>
  .active {
    color: blue;
  }
</style>

<div class:class={isActive ? 'active' : ''}>
  이 div는 isActive가 true일 때 파란색입니다.
</div>

 

 

- style:property

: style: 지시문은 요소에 여러 스타일을 설정하는 축약형을 제공합니다.

<!-- These are equivalent -->
<div style:color="red">...</div>
<div style="color: red;">...</div>

<!-- Variables can be used -->
<div style:color={myColor}>...</div>

<!-- Shorthand, for when property and variable name match -->
<div style:color>...</div>

<!-- Multiple styles can be included -->
<div style:color style:width="12rem" style:background-color={darkMode ? 'black' : 'white'}>...</div>

<!-- Styles can be marked as important -->
<div style:color|important="red">...</div>

: style: 지시문이 style 속성과 결합되면, 지시문이 우선적으로 적용됩니다:

 

- use:action

: 액션은 요소가 생성될 때 호출되는 함수입니다. 액션은 요소가 언마운트된 후에 호출되는 destroy 메서드를 반환하는 객체를 반환할 수 있습니다.

action = (node: HTMLElement, parameters: any) => {
	update?: (parameters: any) => void,
	destroy?: () => void
}

 

<script>
	/** @type {import('svelte/action').Action}  */
	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 />

: 액션은 매개변수를 가질 수 있습니다. 반환된 값에 update 메서드가 있는 경우, 해당 매개변수가 변경될 때마다 Svelte가 마크업 업데이트를 적용한 직후에 호출됩니다.

* foo 함수를 모든 컴포넌트 인스턴스마다 재선언하는 것에 대해 걱정하지 마세요. Svelte은 로컬 상태에 의존하지 않는 모든 함수를 컴포넌트 정의 외부로 끌어올립니다.



- transition:fn

transition:fn
transition:fn={params}
transition:fn|global
transition:fn|global={params}
transition:fn|local
transition:fn|local={params}
transition = (node: HTMLElement, params: any, options: { direction: 'in' | 'out' | 'both' }) => {
	delay?: number,
	duration?: number,
	easing?: (t: number) => number,
	css?: (t: number, u: number) => string,
	tick?: (t: number, u: number) => void
}

: transition은 상태 변경으로 인해 요소가 DOM에 들어오거나 나갈 때 트리거됩니다.

: 블록이 트랜지션 아웃되는 경우, 자체적인 전환을 가지지 않는 요소를 포함하여 블록 내부의 모든 요소는 블록의 모든 전환이 완료될 때까지 DOM에 유지됩니다.

: transition: 지시문은 양방향 전환을 나타냅니다. 즉, 전환이 진행 중일 때 매끄럽게 반전될 수 있습니다.

{#if visible}
	<div transition:fade>fades in and out</div>
{/if}

 

: 전환은 기본적으로 로컬입니다(버전 3에서는 전역이 기본값이었습니다). 로컬 전환은 부모 블록이 생성되거나 제거될 때가 아니라 해당 블록이 생성되거나 제거될 때만 재생됩니다.

{#if x}
	{#if y}
		<!-- Svelte 3: <p transition:fade|local> -->
		<p transition:fade>fades in and out only when y changes</p>

		<!-- Svelte 3: <p transition:fade> -->
		<p transition:fade|global>fades in and out when x or y change</p>
	{/if}
{/if}

 

* 기본적으로 intro 전환은 처음 렌더링 시 재생되지 않습니다. 전환을 전역으로 표시하여 intro: true로 설정하면 이 동작을 수정할 수 있습니다. 전환 매개변수permalink 액션과 마찬가지로 전환에도 매개변수를 사용할 수 있습니다. (이중 {{중괄호}}는 특별한 구문이 아닙니다. 이것은 표현식 태그 내부의 객체 리터럴입니다.)

 

 

- Transition parameters

: 액션과 마찬가지로 전환에도 매개변수를 사용할 수 있습니다.

(이중 {{중괄호}}는 특별한 구문이 아닙니다. 이것은 표현식 태그 내부의 객체 리터럴입니다.)

{#if visible}
	<div transition:fade={{ duration: 2000 }}>fades in and out over two seconds</div>
{/if}

 

Custom transition functions

: 전환은 사용자 정의 함수를 사용할 수 있습니다. 반환된 객체에 css 함수가 있는 경우 Svelte는 해당 요소에 재생되는 CSS 애니메이션을 생성합니다.

: css에 전달된 t 인수는 이징 함수가 적용된 0과 1 사이의 값입니다. 0부터 1까지 실행되는 전환은 1부터 0까지 실행되는 아웃 전환입니다. 즉, 1은 전환이 적용되지 않은 상태로 요소의 자연 상태입니다. u 인수는 1 - t와 같습니다.

 : 이 함수는 전환이 시작되기 전에 t와 u 인수가 다른 값으로 반복해서 호출됩니다.

<script>
	import { elasticOut } from 'svelte/easing';

	/** @type {boolean} */
	export let visible;

	/**
	 * @param {HTMLElement} node
	 * @param {{ delay?: number, duration?: number, easing?: (t: number) => number }} params
	 */
	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}

 

: 사용자 정의 전환 함수는 tick 함수를 반환할 수도 있으며, 이 함수는 동일한 t와 u 인수로 전환 중에 호출됩니다.

* tick 대신에 css를 사용할 수 있는 경우에는 css를 사용하세요. CSS 애니메이션은 주 스레드에서 실행되지 않아 느린 장치에서 장애가 발생하지 않습니다.

<script>
	export let visible = false;

	/**
	 * @param {HTMLElement} node
	 * @param {{ speed?: number }} params
	 */
	function typewriter(node, { speed = 1 }) {
		const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;

		if (!valid) {
			throw new Error(`This transition only works on elements with a single text node child`);
		}

		const text = node.textContent;
		const duration = text.length / (speed * 0.01);

		return {
			duration,
			tick: (t) => {
				const i = ~~(text.length * t);
				node.textContent = text.slice(0, i);
			}
		};
	}
</script>

{#if visible}
	<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}

 

: 전환 객체 대신에 함수를 반환하는 경우, 해당 함수는 다음 마이크로태스크에서 호출됩니다. 이를 통해 여러 전환을 조정하여 교차 페이드 효과를 가능하게 할 수 있습니다.

: 전환 함수는 options라는 세 번째 인수도 받으며, 이 인수에는 전환에 대한 정보가 포함됩니다. options 객체에서 사용 가능한 값은 다음과 같습니다

      :  direction - 전환의 유형에 따라 in, out 또는 both 중 하나입니다.

 

 

- Transition events

: 전환을 가진 요소는 표준 DOM 이벤트 외에도 다음 이벤트를 발송합니다:

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}

 

 

- in:fn/out:fn

in:fn
in:fn={params}
in:fn|global
in:fn|global={params}
in:fn|local
in:fn|local={params}
out:fn
out:fn={params}
out:fn|global
out:fn|global={params}
out:fn|local
out:fn|local={params}

: transition:와 유사하지만, DOM에 진입(in:)하거나 이탈(out:)하는 요소에만 적용됩니다.

: transition:와 달리, in:와 out:으로 적용된 전환은 양방향이 아닙니다. 즉, 전환 중에 블록이 이탈될 경우 전환은 반대로 되돌아가지 않고 계속 진행됩니다. 만약 out 전환이 중단되면, 전환은 처음부터 다시 시작됩니다.

{#if visible}
	<div in:fly out:fade>flies in, fades out</div>
{/if}

 

- animate:fn

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
}

: 키가 지정된 각 블록의 내용이 재정렬될 때 애니메이션이 트리거됩니다. 애니메이션은 요소가 추가되거나 제거될 때는 실행되지 않으며, 기존 데이터 항목의 인덱스가 변경될 때만 실행됩니다. 애니메이션 지시문은 키가 지정된 각 블록의 직계 자식 요소에 있어야 합니다.

애니메이션은 Svelte의 내장 애니메이션 함수 또는 사용자 정의 애니메이션 함수와 함께 사용할 수 있습니다.

 


Animation Parameters

: 액션과 전환과 마찬가지로, 애니메이션에는 매개변수를 가질 수 있습니다.

(이중 {{curlies}}는 특별한 구문이 아닙니다. 이는 표현식 태그 내부에 있는 객체 리터럴입니다.)

{#each list as item, index (item)}
	<li animate:flip={{ delay: 500 }}>{item}</li>
{/each}

 

 

- Custom animation functions

: 애니메이션은 노드, 애니메이션 객체 및 매개변수를 인수로 제공하는 사용자 정의 함수를 사용할 수 있습니다. 애니메이션 매개변수는 from과 to 속성을 포함한 객체입니다. 각 속성은 요소의 시작 및 끝 위치에 대한 DOMRect를 설명합니다. from 속성은 요소의 시작 위치에 대한 DOMRect이고, to 속성은 목록이 재정렬되고 DOM이 업데이트된 후 요소의 최종 위치에 대한 DOMRect입니다.

: 반환된 객체에 css 메서드가 있는 경우, Svelte는 해당 요소에서 재생되는 CSS 애니메이션을 생성합니다.

: css에 전달된 t 인수는 이징 함수가 적용된 후 0과 1 사이의 값입니다. u 인수는 1 - t와 같습니다.

: 이 함수는 애니메이션이 시작되기 전에 t와 u 인수가 다른 값으로 반복해서 호출됩니다.

<script>
	import { cubicOut } from 'svelte/easing';

	/**
	 * @param {HTMLElement} node
	 * @param {{ from: DOMRect; to: DOMRect }} states
	 * @param {any} params
	 */
	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}


: 사용자 정의 애니메이션 함수는 tick 함수를 반환할 수도 있으며, 이 함수는 동일한 t와 u 인수로 애니메이션 중에 호출됩니다.

* tick 대신에 css를 사용할 수 있는 경우에는 css를 사용하세요. CSS 애니메이션은 주 스레드에서 실행되지 않아 느린 장치에서 장애가 발생하지 않습니다.

 

 

 

Reference) 위 내용은 Svelte 공식 문서의 내용을 번역한 내용입니다.

 

Element directives • Docs • Svelte

Edit this page on GitHub On this page On this page As well as attributes, elements can have directives, which control the element's behaviour in some way. on:eventname={handler}on:eventname|modifiers={handler} Use the on: directive to listen to DOM events.

svelte.dev

 

728x90
반응형

'개발 공부 > Svelte' 카테고리의 다른 글

Svelte) Special elements  (1) 2023.10.15
Svelte) Component directives  (1) 2023.10.15
Svelte) Special-tags  (0) 2023.09.18
Svelte) Logic Blocks  (0) 2023.09.18
Svelte) Basic markup  (1) 2023.09.18