$ npm i -D svelte-spa-router
참고 : define-your-routes
<!-- ~/App.svelte -->
<script>
import Router from 'svelte-spa-router'
import routes from '~/routes'
import Header from '~/components/Header.svelte'
</script>
<Header />
<Router {routes} />
<style lang="scss"></style>
// ~/routes/index.js
import Home from '~/routes/Home.svelte'
import Movie from '~/routes/Movie.svelte'
import About from '~/routes/About.svelte'
export default {
'/': Home,
'/movie/:id': Movie, // 파라미터가 있는 페이지
'/about': About
}
파라미터를 컴포넌트에서 사용하기 위한 방법으로 props를 내려받듯이 params
라는 변수를 선언하여 해당 페이지의 파라미터
를 가져올 수 있다.
params
라는 변수는 스벨트에서 일반적인 props와 달리 예약어 개념처럼 명칭이 정해져 있어서 props
와 혼동하지 않도록 주의할 것.
<!-- Movie.svelte -->
<script>
export let params = {}
</script>
<h1>Movie!</h1>
<!--
여기서 id 라는 키값은 :id 값과 동일해야한다.
index.js에서 :abcd 로 작성하면 {params.abcd} 로 파라미터를 가져와야 한다.
-->
<h2>{params.id}</h2>
연결된 주소가 아래와 같다면
아래와 같이 렌더링된다.
index.js
에서 '/movie/:id'
를 '/movie/:abcd'
로 고치면 undefined
가 출력된다.
예를들어 쿼리스트링 값이 이와 같을 때 http://localhost:8080/#/about?pageNo=2&id=22
아래와 같이 쿼리스트링을 가져올 수 있다.
<script>
import { querystring } from "svelte-spa-router";
console.log($querystring) // pageNo=2&id=22
</script>
<div>{ $querystring }</div>
path 값만 깔끔하게 가져오고 싶을 때 location을 사용할 수 있다.
<script>
import { location } from 'svelte-spa-router'
console.log( $location ) // /sub/12
</script>
<div>{ $location }</div>
vue
에서는 <RouterLink>
와 같은 태그를 사용하여 라우터 링크를 적용했지만 svelte
에서는 a
태그에 use:link
속성을 넣으면 라우터 링크를 적용할 수 있다.
href
에는 이동할 경로를 a 태그 사용법과 동일하게 적용하면 된다.
<script>
// 깔끔한 해시 모드 경로 변경
import { link } from 'svelte-spa-router'
</script>
<header>
HEADER!
<a use:link href="/">Home</a>
<a use:link href="/about">About</a>
</header>
disabled
값에 true
를 할당하면 라우터 링크는 클릭이 안되는 비활성 상태가 된다.
<a
href="/about"
use:link={{ disabled: true }}
</a>
아래와 같이 데이터로 동적 처리도 가능.
<script>
let disabled = true
</script>
<a
href="/about"
use:link={{ disabled: disabled }}
</a>
// 키, 벨류가 같으면 생략 가능하기 때문에 아래처럼 단축 가능
use:link={{ disabled }}
<!-- Header.svelte -->
<script>
import { link } from 'svelte-spa-router'
import active from 'svelte-spa-router/active' // active 관련 기능 import
</script>
<header>
HEADER!
<a
href="/"
use:link
use:active={'/'} <!-- href 값과 일치할 경우 ={'/'} 생략 가능 -->
>
Home
</a>
<a
href="/about"
use:link
use:active={'/about'} <!-- 경로를 직접 설정하여 active 클래스 추가 가능 -->
>
About
</a>
</header>
렌더링 된 화면
라우터 링크 active 옵션
svelte-spa-router
의 active 옵션
<!-- 상세 옵션 추가 가능 -->
<a
href="/hello/user"
use:link
use:active={{
path: '/hello/*',
className: 'active_on',
inactiveClassName: 'inactive'
}}>
Hello!
</a>
<!-- 경로만 넣을 때 -->
<a
href="/hello/user"
use:link
use:active={'/hello/*'}>
Hello!
</a>
<!-- 생략 하면 기본값은 active -->
<a
href="/hello/user"
use:link
use:active>
Hello!
</a>
option.path
: 일치하는 경우 링크 활성화 하며/hello/*
와 같이 표기하면 경로 와일드카드로 별표 이후 모든 경로와 일치시킬 수 있다.
또한 이 path 값이 누락되면 현재 페이지의 경로와href
값이 일치할 경우 default 값으로active
클래스를 추가함.
- path 값으로 정규표현식을 사용할 수도 있다.
예를들어 라우터 링크가 /sub 페이지와 /sub/12 페이지 둘다 active 클래스가 붙게 하고 싶다면 아래와 같은 정규식으로 또는 조건식으로 처리할 수 있다.
ex) use:active={{ path: /\/sub|\/sub\/*/ }}
option.className
: 선택 사항이며, active 클래스 이름. 누락시 클래스 이름은active
가 기본 값.option.inactiveClassName
: 선택 사항이며, 현재 페이지가 아닐 경우 라우터 링크에 붙여줄 클래스 이름. 누락시 해당 클래스를 붙이지 않는다.
참고 : dynamically-imported-components-and-code-splitting
SPA(Single Page Application)의 단점 중 하나는 첫화면 로딩시 프로젝트의 모든 코드를 불러와서 성능 저하를 일으킨다는 점이다.
이런 단점을 극복하기 위해 SPA에서는 해당 페이지에 접근할 때 리소스를 다운받을 수 있는 svelte-spa-router
의 code-splitting
기능으로 보완할 수 있다.
이렇게 하면 규모가 큰 SPA 프로젝트에서도 첫화면 렌더링 속도를 드라마틱하게 줄일 수 있다.
// routes/index.js
import { wrap } from 'svelte-spa-router/wrap'
import Main from '@/routes/Main.svelte'
export default {
"/": Main,
"/sub": wrap({
asyncComponent: () => import("@/routes/SubPage.svelte"),
}),
"/sub/:id": wrap({
asyncComponent: () => import("@/routes/SubDesc.svelte"),
}),
"*": wrap({
asyncComponent: () => import("@/routes/NotFound.svelte"),
}),
};
참고 : Navigating programmatically
<script>
import { push, pop, replace } from "svelte-spa-router";
</script>
<button type="button" on:click={() => push('/about')}>about 페이지로 이동</button>
<button type="button" on:click={() => pop()}>뒤로가기</button>
<!-- replace는 push랑 동일하지만 browser history가 안남아서 뒤로가기 기능을 의도적으로 누락 시킬 필요가 있을 때 유용 -->
<button type="button" on:click={() => replace('/about/32')}>about/32 페이지로 이동</button>
아래와 같이 함수 생성하여 별도 처리도 가능
<script>
const goAbout = () => push('/about')
</script>
<button type="button" on:click={goAbout}