Skip to content

Commit

Permalink
modify post 2024-02-29
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmin93 committed Mar 8, 2024
1 parent db88e79 commit a45e2be
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
86 changes: 86 additions & 0 deletions _posts/2024-02-23-svelte5-runes-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,92 @@ Runes는 Svelte 5에서 도입된 핵심 개념으로, 이 반응성을 강화
<span class="text-lg">Number: {valueObject.num}</span>
```

#### sveltekit 에서 외부 js 파일로 사용하기

[Svelte 공식문서 예제](https://svelte.dev/blog/runes#beyond-components) 를 따라해 보았습니다. 별도의 js/ts 파일에서 runes 을 사용하려면 확장자가 `.svelte.js` 또는 `.svelte.ts` 이어야 합니다.

> `counter.svelte.js`
😱 **주의**: 반응형 변수(`$state`)는 반드시 클래스 또는 함수 멤버여야 한다.

```js
export function createCounter() {
let count = $state(0);
// let count = 0; // 안변함 (반응형 변수가 아니라서)
return {
get count() {
return count;
},
increment: () => (count += 1),
};
}
```

> `test-page.svelte`
```html
<script>
import { createCounter } from './counter.svelte.js';
const counter = createCounter();
</script>

<button on:click={counter.increment}>
clicks: {$counter}
</button>
```

#### 자식 컴포넌트에 반응형 객체를 전달하기

> `Child.svelte`
구조가 해제된 변수(destructured variable)의 JDoc 타입 표현은 `@type` 으로 구조를 모두 풀어쓰면 된다.

- 참고 : [How to document destructured variable with jsdoc](https://stackoverflow.com/a/72012216/6811653)
- [Snippet 의 타입](https://svelte-5-preview.vercel.app/docs/snippets#typing-snippets)`import('svelte').Snippet` 이다.
- `@render` 지시자로 처리하고, 파라미터로 동적으로 생성할 수 있다.
- `children` 스니펫은 하위 컴포넌트 태그 안의 모든 내용을 지시하는 예약어이다.
- 별도의 이름은 `{#snippet}...{/snippet}` 으로 지정할 수 있다. [Demo](https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE41S247aMBD9lVFYCegGsiDxks1G7T_0bdkHJ3aI1cR27aEtsvzvtZ0LZeGhiiJ5js-cmTMemzS8YybJ320iSM-SPPmmVJImeFEhML9Yh8zHRp51HZDC1JorLI_iiLxXUiN8J1XHoNGyh-U2i9F2SFy-epon1lIY9IwzRwNv8B6wI1oIJXNYEqV8E8sUfuIlh0MKSvPaX-zBpZ-oFRH-m7m7l5m8uyfXLdOaX5X3V_bL9gAu0D98i0V2NSWKwQ4lSN7s0LKLbgtsyxgXmT9NiBe-iaP-DYISSTcj4bcLI7hSDEHL3yu6dkPfBdLS0m1o3nk-LW9gX-gBGss9ZsMXuLu32VjZBdfRaelft5eUN5zRJEd9Zi6dlyEy_ncdOm_IxsGlULe8o5qJNFgE5x_9SWmpzGp9N2-MXQxz4c2cOQ-lZWQyF0Jd2q_-mjI9U1fr4FBPE8iuKTbjjRt2sMBK0svIsQtG6jb2CsQAdQ_1x9f5R9tmIS-yPToK-tNkQRQGL6ObCIIdEpH9wQ3p-Enk0LEGXwe4ktoX2hhFai5Ofi0jPnYc9QF1LrDdRK-rvXjerSfNitQ_TlqeBc1hwRi7yY3F81MnK9KtsF2n8Amis44ilA7VtwfWTyr-kaKV-_X4cH8BTOhfRzcEAAA=)
- 가끔 `Svelte SSR validation error` 이 나오는데 다시 시작하면 없어진다.

```html
<script>
/**
* @type { {
* counter: {
* count:number,
* increment:()=>void
* },
* children: import('svelte').Snippet
* childTitle: import('svelte').Snippet
* } }
*/
let { counter, children, childTitle } = $props();
</script>

<h2 class="text-2xl">{@render children()} : {@render childTitle()}</h2>
<button class="btn" on:click={counter.increment}>click: {counter.count}</button>
```

> `test-page.svelte`
```html
<script>
import Child from './Child.svelte';
import { createCounter } from './counter.svelte';
const counter = createCounter();
</script>

<h1 class="text-4xl font-bold">TEST</h1>
<Child {counter}>
Child Page
{#snippet childTitle()}
<span class="text-red-500">Counter</span>
{/snippet}
</Child>
```

### 반응형 라이프 사이클 `$effect`

`$state` 변수의 상태에 따라 뭔가를 처리하려면 `$effect` 안에서 해야 한다. 어떻게 보면 `$derived` 와 비슷한데, 반응형 코드 블럭을 수행하던 `$: {...}` 를 대체한다고 여기면 된다.
Expand Down
51 changes: 51 additions & 0 deletions _posts/2024-02-29-svelte5-runes-example2.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,57 @@ dropdown 형태의 Auth 메뉴를 구현하기 위해, 열린 후 바깥쪽을
</div>
```
### dialog 자식 컴포넌트 제어
반응형 선언이 필요없는 경우인데, $state 사용하라고 메시지로 권고한다. [이슈 #10435](https://github.com/sveltejs/svelte/issues/10435) 에서 다뤄진 것처럼 무시하도록 반영될 듯하다. 거슬리지만 preview 버전인 만큼 그냥 넘어가야 한다.
> parent
```html
<script>
import { LoginDialog } from '$lib/components';
/** @type {(open:boolean)=>void} */
let showDialog;
// [메시지]
// showDialog is updated, but is not declared with $state(...).
// Changing its value will not correctly trigger updates.
/**
* loginDialogEl 오픈
* @param {Event} event
*/
function openDialog(event) {
showDialog(true);
}
</script>
<button class="btn" onclick={openDialog}>open modal</button>
<LoginDialog bind:showDialog />
<!-- <svelte:component this={LoginDialog} bind:showDialog /> -->
```
> child
```html
<script>
/** @type {HTMLDialogElement} */
let dialogEl;
/** @param {boolean} open */
export let showDialog = function (open) {
if (open) {
dialogEl.show();
}
};
</script>
<dialog bind:this={dialogEl} class="modal">
<!-- ... -->
</dialog>
```
### UI 라이브러리와 호환성
아직은 어떤 원인으로 그런지 모르겠지만, svelte 5 preview 가 딱지를 떼고 라이브러리들도 호환성 명시를 해주지 않는 이상 사용은 불가능한 것으로 보인다.
Expand Down

0 comments on commit a45e2be

Please sign in to comment.