Post

LUVIT 새로운 웹 개발의 시작 스벨트2

LUVIT 새로운 웹 개발의 시작 스벨트2

들어가며

이 포스트는 오시내님의 「LUVIT 새로운 웹 개발의 시작 스벨트」 5장부터 10장까지 읽고 개인적으로 학습한 내용을 정리한 글입니다.

  • 책: LUVIT 새로운 웹 개발의 시작 스벨트
  • 저자: 오시내
  • 출판사: 제이펍
  • 챕터: 5 ~ 10장

핵심 내용 정리

5장 반응성

삼항 연산자 반응성 코드

1
2
3
4
5
6
7
8
<script>
    let count = 1;
    const handleClick = () => count++;
    
</script>
<button on:click={handleClick}>
     클릭  : {count} { count === 1 ? 'time' : 'times'}
</button>

스크립트 반응성 코드

변수 선언형 반응성 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
    let count = 1;

    // 반응성 변수 선언
    $: doubled = count * 2;
    $: square = count * count;

    const handleClick = () => count++;
</script>

<button on:click={handleClick}>
    클릭  : {count}
</button>
<h3>  구하기</h3>
<p> {count } x 2 = {doubled}</p>
<h3>제곱 구하기</h3>
<p> {count} x {count} = {square}</p>

$:의 그룹화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
    let count = 1;

    // 반응성 변수 선언
    $: doubled = count * 2;
    $: square = count * count;

    $: {
         console.log('두 배 값:' + doubled);
         console.log('제곱 값:' + square);

    }

    const handleClick = () => count++;
</script>

<button on:click={handleClick}>
    클릭  : {count}
</button>
<h3>  구하기</h3>
<p> {count } x 2 = {doubled}</p>
<h3>제곱 구하기</h3>
<p> {count} x {count} = {square}</p>

$:조건절

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
    let count = 1;

    $: if(count >= 10){
        alert('10개 이상 구매할 수 없다');
        count = 9;
    }
    $: if(count <= 0>){
        alert('최소 구매 개수 1개');
        count = 1;
    }

    const plusHandle = () => count++;
    const minusHandle = () => count--;

</script>

<button on:click={minusHandle}>-</button>
<input type="text" value="{count}">
<button on:click={plusHandle}>-</button>

6장 이벤트 문법

스벨트 이벤트 사용 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
    let m = {x:0, y: 0};

    const handleMouseMove = e =>{
        m.x = e.clientX;
        m.y = e.clientY;
    }
</script>

<div on:mousemove={handleMouseMove} role="presentation">
    x 좌표 : {m.x} <br>
    y 좌표 : {m.y}
</div>

인라인 이벤트 사용 방법

1
2
3
4
5
6
7
8
9
<script>
    let m = {x:0, y: 0};

</script>

<div on:mousemove={e => m = {x:clientX, y : e.clientY}} role="presentation">
    x 좌표 : {m.x} <br>
    y 좌표 : {m.y}
</div>

함수 매개변수 사용

1
2
3
4
5
6
7
<script>
    const handleClick01 = text => alert(`${text} 클릭!`);
    const handleClick02 = text => alert(`${text} 클릭!`);
</script>

<button on:click={() => handleClick01('1번')}>  번째 버튼</button>
<button on:click={() => handleClick02('2번')}>  번째 버튼</button>

once 수식어 사용

1
2
3
4
5
6
7
<script>
    const handleClick01 = () => alert('클릭은 한번만');
    const handleClick02 = () => alert('클릭 계속');
</script>

<button on:click|once={handleClick01}>클릭01</button>
<button on:click={handleClick02}>클릭02</button>

preventDefault 수식어

1
2
3
4
5
6
7
8
9
10
<script>
    const handleClick = () =>{
        let move = confirm('제이펍 사이트로 이동?');
        move && location.assign('http://jpub.kr');
    }
</script>

<h1>
    <a href="http://jpub.kr" on:click|preventDefault={handleClick}>제이펍 출판사</a>
</h1>

7장 props(25-07-09 작성)

props

  • 부모 컴포넌트가 자손 컴포넌트에게 전달하는 값
  • 컴포넌트가 자식, 부모 컴포넌트로 제적해야함
1
2
3
4
5
6
7
8
9
10
11
12
// 자식 컴포넌트
<script>
    export let name;
    export let age;
    export let hobby;
</script>

<h3>이름 : {name}</h3>
<h3>나이 : {age}</h3>
<h3>취미 : {hobby}</h3>

1
2
3
4
5
6
7
8
9
10
// 부모 컴포넌트
<script>
    import child01 from "./child01.svelte";
</script>

<child01 name={'김철수'} age = {20} hobby = {'축구하기'}>
<child01 name="이영희" age = 21 hobby = "넷플릭스보기">


props 기본값 설정

1
2
3
4
5
6
7
8
9
10
11
12
// 자식 컴포넌트
<script>
    export let name = " 홍길동";
    export let age = 20;
    export let hobby = "독서";
</script>

<h3>이름 : {name}</h3>
<h3>나이 : {age}</h3>
<h3>취미 : {hobby}</h3>

props 데이터 변경

1
2
3
4
5
6
7
8
9
10
11
12
// 자식 컴포넌트
<script>
    export let name = " 홍길동";
    export let age = 20;
    export let hobby = "독서";
</script>

<h3>이름 : {name}</h3>
<h3>나이 : {age}</h3>
<h3>취미 : {hobby}</h3>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
    import child01 from "./child01.svelte"
    let age01 = 20;
    let age02 = 21;

    const agePlus = () =>{
        age01++;
        age02++;
    }

    const ageMinus = () =>{
        age01--;
        age02--;
    }
</script>
<child01 name={'김철수'} age = {20} hobby = {'축구하기'}>
<child01 name="이영희" age = 21 hobby = "넷플릭스보기">
<button on:click={ageMinus}>나이 감소-</button>
<button on:click={agePlus}>나이 증가+</button>

스프레드 props

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 자식 컴포넌트
<script>
    import child03 from "./child03.svelte";
    const allData01 = {
        name: '김철수',
        age: 20,
        hobby: '축구하기'
    }
</script>

<h3>이름 : {name}</h3>
<h3>나이 : {age}</h3>
<h3>취미 : {hobby}</h3>

<child03 {...allData01}>
<child03 {...allData02}>

8장 스벨트 로직(25-07-10 작성)

if, else-if, else 블록 기본 문법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
	let x = null;
	const numChange = e => x = e.target.value;
</script>

<label for="testBox">양수/음수 테스트</label>
<input type="text" id="testBox" on:keyup={numChange} placeholder="정수를 입력하세요.">

{#if x > 0}
	<p>작성한 숫자는 양수입니다.</p>
{:else if x < 0}
	<p>작성한 숫자는 음수입니다.</p>
{:else if x === '0'}
	<p>작성한 숫자는 0입니다.</p>
{:else}
	<p>정수로 다시 입력하세요.</p>
{/if}

each 블록 기본 문법 전체

1
2
3
4
5
6
7
8
<script>
	let teams = ['LG 트윈스','KT 위즈','SSG 랜더스','NC 다이노스','두산 베어스','KIA 타이거즈','롯데 자이언츠','삼성 라이온즈','한화 이글스','키움 히어로즈'];
</script>

<h3>2023 KBO 정규리그 순위</h3>
{#each teams as team,i}
	<p>{i + 1} : {team}</p>
{/each}

객체 데이터 반복문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script>
	let langs = [
        {
            id: 1,
            name: '스벨트(Svelte)',
            release: 2016,
            src: 'https://svelte.dev/favicon.png',
        },
        {
            id: 2,
            name: '리액트(React)',
            release: 2013,
            src: 'https://ko.legacy.reactjs.org/favicon.ico',
        },
        {
            id: 3,
            name: '뷰(Vue.js)',
            release: 2013,
            src: 'https://v2.ko.vuejs.org/images/logo.png',
        }
    ];

</script>

<h3> 프론트엔드 언어</h3>
{#each langs as lang (lang.id) }
	<div style="border: 2px solid black; width: 200px; padding: 10px;">
        <h4>이름 : { lang.name }</h4>
        <p>배포 년도 : { lang.release }</p>
        <img src={ lang.src } alt={ lang.name } height="50">
    </div>
{/each}

9장 폼 관련 요소 바인딩

  • 바인딩 : 상태값과 그 값을 제어하는 요소 간의 결합
    • 단방향 바인딩 : 요소가 상태값을 직접 변화시키지 못함. props가 예시
    • 양방향 바인딩 : 입력과 출력이 동시에 변경되도록 처리

입력 요소 관련 바인딩

input값 바인딩 - text, number, checkbox, radio, textarea 버튼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
	let name = '';
    let a = 1;
	let b = 2;
    let chk = false;
</script>

<input type="text" bind:value={name} placeholder="이름을 입력하세요.">
<p>안녕! {name || '낯선 사람'}!</p>

<label>
	<input type="number" bind:value={a} min="0" max="10">
	<input type="range" bind:value={a} min="0" max="10">
</label>

<label>
	<input type="number" bind:value={b} min="0" max="10">
	<input type="range" bind:value={b} min="0" max="10">
</label>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script>
	let chk = false;
    let choiceSize = 0;
	let sizes = ['Tall','Grande','Venti'];
    let text = '내용을 입력하세요.';
</script>

<label>
	<input type="checkbox" bind:checked={chk}> 약관 동의
</label>
{#if chk}
	<p>당신은 약관에 동의했습니다.<br>이제 구독이 가능합니다.</p>
{:else}
	<p>당신은 약관에 동의하지 않았습니다.<br>아직 구독이 불가능합니다.</p>
{/if}
<button disabled={!chk}>
	구독
</button>


<h3>사이즈 선택</h3>
{#each sizes as size, i}
	<label>
		<input type="radio" bind:group={choiceSize} value={i}>
		{ size }
	</label>
{/each}

<p>고객님은 {sizes[choiceSize]} 선택하셨습니다.</p>

<textarea bind:value={text} rows="5" />
<p>{text}</p>

선택 바인딩

  • select 값 바인딩 - 단일 선택 ```javascript

    const selectChange = () => { if(selected != null){ window.open(selected); } } </script>

포털 사이트 바로가기

<select bind:value={selected} on:change={selectChange}> {#each portals as portal} <option value={portal.url}>{ portal.name }</option> {/each} </select>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- select 값 바인딩 - 다중 선택
```javascript

<script>
	let foods = ['떡볶이','순대','오뎅','튀김'];
    let selected = '';
</script>

<h3>OSSAM 분식</h3>
<select multiple bind:value={selected}>
	{#each foods as food}
		<option value={food}>{ food }</option>
	{/each}
</select>
{#if selected.length === 0}
    <p>주문하실 메뉴를 선택해 주세요.</p>
{:else}
    <p>선택 메뉴 : {selected}</p>
{/if}

10장 기타 요소 바인딩

  • 바인딩 방법 & 이벤트 처리 함수 추가하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script>
    let buckets = [
		{ chk: false, text: '웹 프론트엔드 개발자되기' },
		{ chk: false, text: '유럽 여행하기' },
		{ chk: false, text: '영국 가서 손흥민 축구 경기 보기' }
	];
    $: remaining = buckets.filter(bucket => !bucket.chk).length;

    const onAdd = () => {
        buckets = buckets.concat({ chk: false, text: '' });
    }
    const onRemove = () => {
        buckets = buckets.filter(bucket => !bucket.chk);
    }
</script>

<h1>Bucket List</h1>
{#each buckets as bucket}
    <div>
        <input type="checkbox" bind:checked={bucket.chk} />
        <input type="text" placeholder="당신의 버킷 리스트는 뭔가요?" style="width: 250px" bind:value={bucket.text} disabled={bucket.chk} />
    </div>
{/each}
<p>남은 버킷 리스트 : {remaining}</p>
<button on:click={onAdd}>새로운 버킷 추가</button>
<button on:click={onRemove}>성공한 버킷 제거</button>

멀티미디어 요소 바인딩

  • 멀티미디어 요소(video 등) 바인딩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script>
    let duration;
    let currentTime = 0;
    let paused = true;

    const onPlay = () => paused = false;
    const onPause = () => paused = true;
    const onInitial = () => {
        paused = true;
        currentTime = 0;
    }
</script>

<h1>Caminandes: Llamigos</h1>
<p>From <a href="https://studio.blender.org/films">Blender Studio</a>. CC-BY</p>
<video
    poster="https://sveltejs.github.io/assets/caminandes-llamigos.jpg"
    src="https://sveltejs.github.io/assets/caminandes-llamigos.mp4"
    width="500"
    bind:duration={duration}
    bind:currentTime={currentTime}
    bind:paused={paused}
>
    <track kind="captions" />
</video>
<br />
<button on:click={onPlay}>재생</button>
<button on:click={onPause}>멈춤</button>
<button on:click={onInitial}>초기화</button>
<p> 재생 시간 : {duration}</p>
<p>현재 재생 위치 : {currentTime}</p>

공간 바인딩

  • 블록 요소 바인딩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
    let w;
    let h;
    let size = 20;
</script>

<p>슬라이더로 글자 크기를 변경해보세요.</p>
<input type="range" bind:value={size} min="10" max="100" />
<p>글자 크기 : {size}px</p>
<div bind:clientWidth={w} bind:clientHeight={h}>
    <span style="font-size: {size}px">글자</span>
</div>
<ul>
    <li>가로  : {w}</li>
    <li>세로 높이 : {h}</li>
</ul>


<style>
    div{ display: inline-block; border: 3px solid black; }
</style>

this 바인딩

  • 특정 DOM을 선택하는 방법 -> bind:this 사용하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// this.svelte
<script>
    let text = '';
    let clicked = false;
    let validated = false;
    let inputRef;

    const onValidatedClick = () => {
        clicked = true;
        validated = text === '1234';
        if(!validated){
            inputRef.focus();
        }
    }
</script>

<form>
    <input
        type="password" bind:value={text}
        class={clicked && (validated ? 'success' : 'failure')}
        bind:this={inputRef}
    />
    <button
        type="submit"
        on:click|preventDefault={onValidatedClick}
    >검증하기</button>
</form>

<style>
    .success{ background-color: lightgreen; }
    .failure{ background-color: lightcoral; }
</style>

// App.svelte
<script>
    import This from './This.svelte'
</script>

<This/>
<This/>
<This/>

컴포넌트 바인딩

  • 컴포넌트의 props를 바인딩하는 방법
    • bind를 사용해 부모 컴포넌트의 상태변수와 자식 컴포넌트의 상태변수를 연결
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Parent.svelte
<script>
    import Child from "./Child.svelte";
    let parentValue = 1;
</script>

<Child bind:childValue={parentValue} />
<p>부모  : {parentValue}</p>

// App.svelte
<script>
	import Parent02 from "./Parent02.svelte";
</script>

<Parent02 />

스벨트 slot

This post is licensed under CC BY 4.0 by the author.