Svelte3 + crayonでSPAをやってみる


Svelte3にはrouter的な機能がないようなので
SPAしたい時どうしようかなーと思ったのでメモ書き


今回はcrayonというパッケージを使ってみようと思います
https://github.com/alshdavid/crayon

Svelteの他にもReact, Vueでも動くようです。
またrouterにアニメーション設定することでページ切替時にカッコよくアニメーションさせながら切り替える事ができます!!


#  Svelteのプロジェクトを作る

```console
$ npx degit -f sveltejs/template svelte-app
$ cd svelte-app
$ npm install
```

## 動作確認
```console
$ npm run dev
```

ブラウザで http://localhost:5000 を表示してHello Worldが出ればオッケー

# パッケージのインストール
crayon系のパッケージをインストールします
下の2つはアニメーション用なので不要ならインストールしなくても大丈夫です

```console
$ npm install --save crayon
$ npm install --save crayon-svelte
$ npm install --save crayon-animate
$ npm install --save crayon-transition
```


# 確認用のコンポーネントを用意

`src/App.svelte` を以下の内容に編集します

```html
<script>
    export let nav
</script>

<h1>画面1</h1>
<button
    on:click={() => nav.navigate('/app2')}>
    画面2
</button>
```

`src/App2.svelte` を以下の内容で新規作成します

```html
<script>
    export let nav
</script>

<h1>画面2</h1>
<button
    on:click={() => nav.navigate('/')}>
    画面1
</button>
```

## 画面切り替えの方法
`export let nav`の部分は後で出てきますが、routerの設定で各コンポーネントにRouterオブジェクトを渡すようにしています。
`nav.navigate()`にrouterで定義したパスを渡すことで画面切り替えを行う事ができます。



# [アニメーション無し]Svelte3側の設定
テンプレートで用意されている `main.js` を以下のように編集します。

設定はこれだけです。

```javascript
import crayon from 'crayon'
import svelte from 'crayon-svelte'

import App from './App.svelte'
import App2 from './App2.svelte'

const app = crayon.create()
app.use(svelte.router(document.body))

app.path('/', (req, res) =>
    res.mount(App, { nav: app })
)
app.path('/app2', (req, res) =>
    res.mount(App2, { nav: app })
)

app.load()
```

## 書き換えるDOMの指定
```javascript
app.use(svelte.router(document.body))
```

今回はbodyが書き換えられるようにしていますが
どこかのIDだけ書き換えたければ以下のようにすれば良いです

```javascript
app.use(svelte.router(document.getElementById('app')))
```

## ルーティング
```javascript
app.path('/', (req, res) =>
    res.mount(App, { nav: app })
)
```

パス`/`に対して`App`コンポーネントが使われるようにしています。
`res.mount()`の第２引数に渡した値はコンポーネントのpropsに割り当てられます。
今回は各コンポーネントで画面移動するためにRouterが必要なのでそれだけ渡してます。



# [アニメーションあり]Svelte3側の設定
テンプレートで用意されている `main.js` を以下のように編集します。

```javascript
import crayon from 'crayon'
import svelte from 'crayon-svelte'
import animate from 'crayon-animate'
import transition from 'crayon-transition'

import App from './App.svelte'
import App2 from './App2.svelte'

const app = crayon.create()
app.use(svelte.router(document.body))

// animation
app.use(transition.loader())
app.use(animate.defaults({
    name: transition.fade,
    duration: 300,
}))
app.use(animate.routes([
    { from: '/', to: '/app2', name: transition.slideLeft },
    { from: '/app2', to: '/', name: transition.slideRight },
]))

// route
app.path('/', (req, res) =>
    res.mount(App, { nav: app })
)
app.path('/app2', (req, res) =>
    res.mount(App2, { req, nav: app })
)

app.load()
```

## ページ切替時のアニメーション設定
```js
app.use(animate.defaults({
    name: transition.fade,
    duration: 300,
}))
```

`name: transition.fade`はデフォルトのアニメーション設定です
`animate.routes()`に設定されていないパス間の移動の場合はここで設定したアニメーションをしながらページが切り替わります。

ちなみに`transition`で使えるアニメーションは全部ためしてないですがこれだけあります。

```
slideUp
slideDown
slideLeft
slideRight
pushUp
pushDown
pushLeft
pushRight
popUp
popDown
popLeft
popRight
fade
```

## 特定のパス間の移動時にアニメーションを変える
```js
app.use(animate.routes([
    { from: '/', to: '/app2', name: transition.slideLeft },
    { from: '/app2', to: '/', name: transition.slideRight },
]))
```

`animate.defaults()`に指定したアニメーション以外を使いたい場合は↑のようにすることで
特定パスのアニメーションだけ変更することができます


上記のようにfrom/toのパスを指定しても良いですが
どこから来ても`/app2`に来る時のアニメーションを変更したい、移動先関係なく`/app2`から移動する時のアニメーションを変更したい
となった場合は書くの大変なので、そういう場合は以下のように記述すればよいです。

```js
{ from: '/**', to: '/app2', name: transition.slideLeft },
{ from: '/app2', to: '/**', name: transition.slideLeft },
```