선언적 렌더링
변수 사용
Svelte는 Vue와 비슷하게 <script> 태그 내부에서 선언한 변수를 html 태그에서 사용할 수 있는데 {} 사이에 그 변수 명을 넣어서 사용한다.
<script>
let name = 'world'
</script>
<h1>{name}</h1>
이벤트 바인딩
버튼을 클릭하면 name 변수의 값이 변하는 함수를 만들고 그 함수를 버튼에 바인딩 하려면 on:click={함수} 를 버튼에 입혀주고 함수 이름을 {} 안에 넣어주면 된다.
<script>
let name = 'world'
function assign() {
name = 'Joon'
}
</script>
<h1>{name}</h1>
<button on:click={assign}>
Assign
</button>
input 변수 바인딩
input 태그에 일반 value를 사용하면 단방향 바인딩이 되므로 변수가 표시는 되지만 사용자의 수정 값이 변수에 반영되지는 않는다.
<input type="text" value={name} />
반면 bind:value 를 사용하면 양방향 바인딩이 되므로 사용자의 수정 값이 변수에 반영되게 할 수 있다.
<input type="text" bind:value={name} />
css 적용
vue와 마찬가지로 파일 내에 <style></style> 태그를 사용할 수 있으며 여기에 적용된 스타일은 해당 파일에만 적용된다.
조건문 & 반복문
조건문
toggle 버튼을 눌러서 값이 true이면 이름이 보이고 false면 경고문이 출력되는 예제를 생각해보자. boolean 값인 toggle에 따라서 DOM을 변화시켜야 하기 때문에 자연스레 if else문을 떠올리게 된다. Svelte에서의 조건문은 아래와 같이 사용할 수 있다.
<script>
let name = 'world';
let toggle = false
</script>
<button on:click={() => {toggle = !toggle}}>
Toggle
</button>
{#if toggle}
<h1>Hello {name}!</h1>
{:else}
<div>No name!</div>
{/if}
if문을 시작할 때는 # 을 앞에 붙여주고 조건을 그 뒤에 써준다. if 문의 종료는 / 로 나타내며 중간에 else가 들어갈 때에는 그 앞에 : 를 붙여주면 조건문을 사용할 수 있게 된다.
Svelte에서는 항상 구문 시작에는 # 중간에는 : 끝에는 / 를 사용하므로 외워두면 편하게 사용할 수 있다!!
반복문
프론트 코딩을 하다보면 리스트를 나열해야 할 일이 많은데 Svelte에서도 Vue에서의 v-if와 같은 문법을 제공한다.
<script>
let name = 'Fruits';
let fruits = ['Apple', 'Banana', 'Cherry', 'Orange', 'Mango']
</script>
<h1>Hello {name}!</h1>
<ul>
{#each fruits as fruit}
<li>{fruit}</li>
{/each}
</ul>
Svelte에서의 반복문은 each 를 사용하는데 if else와 마찬가지로 시작부분에는 # 끝 부분에는 / 를 앞에 붙여준다.
#each 오른쪽에는 리스트가 들어가며 구문 내부에서 사용될 각각의 변수명을 as 키워드를 사용해서 지정해줄 수 있다. 리스트 내부에서는 중괄호를 사용하여 각 요소를 나열할 수 있다.
컴포넌트
기존의 Vue나 리액트와 같이 Svelte 또한 컴포넌트화 하여 재사용하는 개념을 사용하고 있다. 이 때 컴포넌트는 독립된 ~.svelte 파일로 존재하게 되며 이 파일의 이름은 대문자로 시작해야 한다. 부모 컴포넌트에서 과일 이름이 들어있는 배열을 생성하고 자식 컴포넌트에서 각 배열을 다르게 표시할 수 있는 예제를 생각해보자.
위 그림은 예제의 최종 결과이며 메인 파일인 App.svelte에서 Fruits.svelte를 호출하는 방식으로 구현하고자 한다. 결과 이미지에서 볼 수 있듯이 배열을 거꾸로 출력하거나 일부를 출력하는 등의 기능도 제공할 수 있어야 한다.
Props
// App.svelte
<script>
import Fruits from './Fruits.svelte'
let fruits = ['Apple', 'Banana', 'Cherry', 'Orange', 'Mango']
</script>
<Fruits {fruits} />
<Fruits {fruits} reverse />
<Fruits {fruits} slice="-2" />
<Fruits {fruits} slice="0, 3" />
// Fruits.svelte
<script>
// Props
export let fruits
export let reverse
export let slice
let computedFruits = []
let name = ''
if (reverse) {
computedFruits = [...fruits].reverse()
name = 'reverse'
} else if (slice) {
computedFruits = fruits.slice(...slice.split(','))
name = `slice ${slice}`
} else {
computedFruits = fruits
}
</script>
<h2>
Fruits {name}
</h2>
<ul>
{#each computedFruits as fruit}
<li>{fruit}</li>
{/each}
</ul>
위 코드는 제시된 조건을 만족하기 위해 작성한 Fruits.svelte의 코드이다. 상위 컴포넌트인 App.svelte에서 Fruits 파일을 import해서 사용하며 거꾸로 뒤집기, 자르기 등의 기능을 사용하기 위해 Props 속성을 Fruits 태그에 제공하고 있다(다른 svelte 파일을 import하면 htlm 태그와 같이 사용할 수 있다).
Svelte에서는 props 값을 받을 때 변수 선언문 앞에 export 예약어를 사용한다. 해당 예약어를 통해 받은 props 값을 통해 하위 컴포넌트에 선언된 변수 값을 변경하고 그에 따라 화면에 표시되는 리스트를 변경할 수 있다.
reverse() 함수
svelte 외적으로 자바스크립트를 쓸 때 주의해야할 사항을 알게 되었다. 배열의 순서를 뒤바꾸는 reverse 메서드는 원래의 배열 자체의 순서를 바꿔버린다. 따라서 A라는 배열에 reverse() 함수를 한번이라도 사용하면 그 밑의 코드에서는 A 배열의 순서가 바뀌어서 들어가게 된다.
따라서 이번 예제에서는 전개연산자를 통해 새로운 배열에 대해 reverse 함수를 사용하여 렌더링에 사용하였다.
slilce() 함수
svelte 외적으로 자바스크립트를 쓸 때 주의해야할 사항을 알게 되었다. 배열의 순서를 뒤바꾸는 reverse 메서드는 원래의 배열 자체의 순서를 바꿔버린다. 따라서 A라는 배열에 reverse() 함수를 한번이라도 사용하면 그 밑의 코드에서는 A 배열의 순서가 바뀌어서 들어가게 된다.
따라서 이번 예제에서는 전개연산자를 통해 새로운 배열에 대해 reverse 함수를 사용하여 렌더링에 사용하였다.
스토어
바로 위에서 부모, 자식 관계의 컴포넌트끼리 데이터를 넘겨받을 수 있는 props에 대해서 알아보았다. 이를 통해 데이터를 이동시켜서 하위 컴포넌트에서 상위 컴포넌트의 데이터를 사용할 수 있지만 부모-자식 관계의 depth가 깊어진다면 어떻게 될까? Vue나 React의 경우 이를 Vuex나 Redux를 사용하여 해결하는데 Svelte또한 이와 비슷한 Store를 가지고 있다.
App.svelte -> Parent.svelte -> Child.svelte 의 구조로 예제를 만들어보자. App.svelte에 있는 name 변수를 Child에서 사용하고자 할 때 props를 통해 계층적으로 내리기 보다 svelte에 내장되어 있는 store를 사용하면 Parent는 사용하지도 않는 props를 받을 필요가 없을 것이다.
store.js 라는 이름의 파일을 만들고(파일명 소문자로 시작) 아래와 같이 공유할 변수를 선언하고 svelte/store 로부터 writable 을 불러와 공유 변수에 할당한다. 그냥 변수를 선언하고 초기화하면 해당 js 파일외부에서 변수를 수정할 수 없기 때문에 writable을 사용해야 한다.
import { writable } from 'svelte/store'
export let storeName = writable('Joon')
참고로 Vue나 React의 경우는 모두 공유 저장소가 외부에 위치하지만 Svelte는 store가 svelte 자체에 내장되어 있다. 또한 writable을 사용해서 생성한 변수(여기서는 storeName)는 객체 형식으로 할당되게 된다.
이 변수 객체는 내장된 3개의 함수를 사용해서 값을 컨트롤 할 수 있지만 여기서는 간단한 사용을 위해 $를 이용하여 Auto-subscription을 사용해서 값에 직접 접근한다.
// App.svelte
<script>
import { storeName } from './store.js'
import Parent from './Parent.svelte'
let name = 'world';
$storeName = name;
</script>
<h1>Hello {name}!</h1>
<Parent />
위 코드에서와 같이 store에서 불러온 writable 객체 앞에 $ 기호를 사용하면 그 값을 변수로 사용할 수 있게 되고 App.svelte에서 그 값을 변경시킬 수 있다.
// Child.svelte
<script>
import { storeName } from './store.js'
</script>
<div>
Child { $storeName }
</div>
Child.svelte에서는 위와 같이 해당 값을 store로부터 improt해서 사용할 수 있으며 여기서도 마찬가지로 값에 직접 접근하기 위해 $ 를 이용해서 auto-subscribe하여 값을 사용하였다.
$ 예약어
위에서 살펴보았듯이 store의 writable 객체 앞에 $ 를 쓰면 특정 수행을 수행하므로 svelte 파일에서는 변수 이름 맨 앞에 $를 사용할 수 없다. 이는 $가 예약어로 쓰이기 때문이며 php를 사용하던 습관이 있는 개발자는 주의해야 할 필요가 있다.
'Svelte' 카테고리의 다른 글
Svelte로 Todo앱 예제 만들기 (0) | 2021.08.17 |
---|---|
Svelte란?? (0) | 2021.08.13 |
댓글