Svelte 입문 강의 - A부터 Z까지 4

4️⃣

🖥 Store

9 - 2. Writable stores

// src/ stores.js
import { writable } from 'svelte/store'

export const count = writable(0);

// src/ App.svelte
<script>
	import { onDestroy } from 'svelte'
	import { count } from './stores.js'

	import Incrementer from './Incrementer.svelte'
	import Decrementer from './Decrementer.svelte'
	import Resetter from './Resetter.svelte'

	let countValue ;

	const unSubscribe = count.subscribe(value => countValue = value);
	onDestroy(unSubscribe)
</script>
	// subscribe 는 count에 값이 변경될때마다 subscribe에 전달될 함수가 콜백된다 ?  
	// 무슨말인지 잘 모르겠다..
	// resetter 나 incrementer 등에서 버튼이 눌려져서 count의 값이 업데이트 됬을때 subcscribe에 인자로 전달된 함수가 호출된다...?

	// count에 값이 변경될때마다 함수가 호출되기때문에 onDestroy를 통해 subscribe 를 해지해야한다고 하는데,
	// 실습을 해봐야확실히 알것같다.. 왜 해지해야하는지..!?

<p>count : { countValue } </p>

<Incrementer></Incrementer>
<Decrementer></Decrementer>
<Resetter></Resetter>

9 - 3. Store 자동 구독

9 - 4. Readable stores

-   `initial`: 첫 번째 파라미터는 초깃값입니다. 초깃값을 설정할 필요가 없을 경우,  `null`이나  `undefined`를 사용할 수 있습니다.
-   `start`: 두 번째 파라미터는 첫 구독자가 발생했을 때 호출되는 함수입니다.  `set`  콜백 함수를 파라미터로 가지고  `stop`  함수를 리턴하는 함수입니다.
-   `set`: 관찰하고 있는 값을 변경하는 콜백 함수입니다.
-   `stop`: 모든 구독자가 구독을 중단하면 호출되는 함수입니다.  `start`  함수에서 사용된 자원들이 있다면, 이 함수 내에서 자원을 해제해야 합니다.
// src/ stores.js
import { readable } from 'svelte/store'

export const time = readable(new Date(), function (set) {
    const interval = setInterval(()=> {
        set(new Date())
    }, 1000)
    return function stop () {
        clearInterval(interval)
    }
})

9 - 5. Derived stores

-   첫 번째 파라미터는 참고하는 store입니다. 참고하는 store가 하나라면  `derived(a, ...)`으로 객체가 됩니다. 참고하는 store가 여러 개라면  `derived([a, ...b], ...)`로 배열이 됩니다.
-   두 번째 파라미터는 새로운 store의 값을 리턴하는 콜백 함수입니다. 콜백 함수의 파라미터는 참고하는 store입니다. 콜백 함수의 마지막 파라미터는  `set`  함수입니다.  `derived([a, ...b], ([$a, ...$b], set) => ...)`와 같은 형태입니다.
-   세 번째 파라미터는 새로운 store의 초깃값입니다. 
// src/ stores.js

// 페이지에 접속하고 나서 몇초가 지났는지 알려주는 함수
const start = new Date();
export const elapsed = derived(time, ($time) => {
  return Math.round(($time - start) / 1000);
});
// 전 9-4에서 사용했던 time 이용

9 - 6. Custom stores

// src/ stores.js
import { writable } from 'svelte/store'

function createCount() {
    const { set, subscribe, update } = writable(0)

    return {
        subscribe,
        increment: () => update(x => x + 1),
        decrement: () => update(x => x - 1),
        reset: () => set(0),
    }
}

export const count = createCount();
// 위와 같이 count라는 커스텀스토어를 만들수 있다.

// src/App.svelte
<script>
import { count } from './stores.js'
console.log(count);

</script>

<p>{ $count }</p>
<button on:click={count.increment}>+</button>
<button on:click={count.decrement}>-</button>
<button on:click={count.reset}>reset</button>

9 - 7. Store bindings

// src/ stores.js
import { writable, derived } from 'svelte/store'

export const name = writable('james')

export const greeting = derived(
    name,
    $name => `Hello, ${$name}`
)

// src/App.svelte
<script>
import { name, greeting } from './stores.js'
</script>

<p>{ $greeting }</p>
<input type="text" bind:value={$name} />

<button on:click={()=> $name += '!'}>Add!!!</button>

🖥 Motion

10 - 1. Motion 이란

10 - 2. Tweened

tweened 함수는 2개의 파라미터를 가집니다. 첫 번째 파라미터는 변경되는 값이고 두 번째 파라미터는 옵션입니다. tweened 함수는 store를 리턴합니다. options에 설정할 수 있는 값을 살펴보겠습니다.

store.setstore.update의 두 번째 파라미터에 options(위에서 설명한 옵션)를 전달할 수 있습니다. 전달된 옵션은 기본값(인스턴스를 생성할 때 사용한 tweened(value, options)options가 기본값입니다.)에 오버라이드(override) 됩니다. setupdate 함수의 리턴 값은 Promise입니다. tween 작업이 완료되면 Promise가 resolve 됩니다.

// src/App.svelte
<script>
import { tweened } from 'svelte/motion'
import { cubicOut } from 'svelte/easing'

const progress = tweened(0, {
	delay: 200,
	duration: 400,
	easing: cubicOut
})

console.log(progress, $progress);

</script>

<progress value={$progress}></progress>

<button on:click={() => $progress = 0}>0%</button>
<button on:click={() => $progress = 0.25}>25%</button>
<button on:click={() => $progress = 0.5}>50%</button>
<button on:click={() => $progress = 0.75}>75%</button>
<button on:click={() => $progress = 1}>100%</button>

10 - 3. Spring

🖥 트랜지션

11 - 1. 트랜지션 사용하기

// src/App.svelte
<script>
import { fade } from 'svelte/transition';
let visible = true;
</script>

<label for="">
	<input type="checkbox" bind:checked={visible}>
	visible
</label>


{#if visible}
	<p transition:fade=>Fade out</p>
{/if}

11 - 2. 트랜지션 종류

11 - 3. 트랜지션 In/Out

// src/App.svelte
<script>
	import { fly, fade } from 'svelte/transition'
	let visible = true;
</script>

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

{#if visible }
	<p
	in:fly=
	out:fade
	>Transition</p
		>
{/if}

11 - 4. 커스텀 트랜지션

11 - 5. 트렌지션 이벤트

// src/App.svelte
<script>
	import {fly} from 'svelte/transition'
	let visible = true;
	let status = '기다리는중..'
</script>

<p>{status}</p>

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

{#if visible}
	<p 
		transition:fly= 
		on:introstart={()=> status='intro start'} 
		on:introend={()=> status='intro end'}
		on:outrostart={()=> status='outro start'}
		on:outroend={()=> status='outro end'}
	>
	transition
	</p>
{/if}

11 - 6. 트렌지션 수식어

// src/App.svelte
<script>
import { slide } from 'svelte/transition';
let items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let showItems = true;
let i = 5 ; // 리스트에 몇번째까지 표시할지 정하는 
</script>

<label>
	<input type="checkbox" bind:checked={showItems} />
	show list
</label>

<label>
	<input type="range" bind:value={i} max="10"/>
</label>

{#if showItems}
	{#each items.slice(0,i) as item,index (index)}
	<div transition:slide|local>
		{item}
	</div>
	{/each}
{/if}

<!-- div가 추가될 경우에만 슬라이드가 먹는다 : local때문에 -->