SvelteでToDoリストを作る
はじめまして、エンジニアの堤です。
かれこれアシアルでは2年弱働いているのですが、初ブログです。
お手柔らかにお願いします。
今回は個人的に気になっているJavaScriptのフレームワーク、Svelteを使ってToDoリストを作ってみます。
「また新しいJavaScriptのフレームワークか…」とうんざりする人もいるかもしれませんが、
Svelteはこ れまでのJavaScriptのフレームワークとは一風変わったアプローチですので、
ちょっと触ってみたいと思います。
Svelteとは
Svelte自体はReactやVueと同じく、いわゆるUIフレームワークですが、
上にも書いた通りアプローチが異なっています。
Svelteのホームページにアクセスすると、
The magical disappearing UI framework
というキャッチコピーが目に入ると思います。
直訳すると「魔法のように消えるUIフレームワーク」といった感じでしょうか。
これは一体どういうことかというと、Svelteではコンパイルされて最終的に出力されるコードは、
すべて”純粋な”JavaScriptだけのコードになります。
そのため、非常に軽量かつ高速なフレームワークになっています。
この辺りの設計思想に関して詳しく知りたい方は、公式のブログ記事をお読みいただければと思います。
それでは、以降で実際にSvelteを使ってみます。
Svelteのインストール
Svelteでは公式にREPLが提供されているので、
それを使って試すこともできるのですが、今回はローカルで開発する場合の手順でやってみます。
まず、公式のガイドで おすすめされているdegit
をインストールします。
※ Node.js v8以上がインストールされている必要があります。
npm install -g degit
以降もドキュメント通りに実行していきます。
ブラウザでlocalhost:5000を開いて「Hello, World!」と表示されればOKです。
degit sveltejs/template todo-list
cd todo-list
npm install
npm run dev
これでSvelteを使う準備自体はできたのですが、追加でsvelte-extras
をインストールします。
このライブラリはSvelteで配列操作を行ったりする場合に必要になるものです。
npm install --save svelte-extras
ToDoリストを作る
以上で準備ができたので、ToDoリストを作ります。
SvelteではVueのように単一ファイルにhtml、JavaScript、CSSをまとめて書くSingle File Component形式での記述が可能なので、
ここでもそのように記述していきます(とはいえ、今回CSSはほぼありませんが…)。
その際 、ファイルの拡張子は.htmlになります。
まずは、ToDoリストの各アイテム用コンポーネントです。
- src/TodoLIstItem.html
<li
class="{ todo.done ? 'todo-li--done': '' }"
on:click="fire('toggle-todo', { todo, index })"
>
{ todo.title }
</li>
<style>
.todo-li--done {
text-decoration: line-through;
}
</style>
正直、今回作成するアプリレベルではTodoListItemと分ける必要もないんですが、
子から親へのイベントも扱ってみたかったので分けてます。
具体的には3行目が該当します。
Svelteでは、html内にon:イベント名
と書くことでイベントを受け取ることができます。
ここではクリックされた際にtoggle-todo
イベントを発火するようにしています。
あとは、2行目でToDoが完了の場合のみCSSのクラスを当てるようにしています。
続いてToDoリストを表示するコンポーネントです。
- src/TodoList.html
<input bind:value="title" type="text">
<button on:click="addTodo(title)">追加</button>
<ul>
{ #each filteredTodos as todo, index }
<TodoListItem {todo} {index} on:toggle-todo="toggleTodo(event)"/>
{ /each }
</ul>
<button on:click="set({ condition: null })">すべて</button>
<button on:click="set({ condition: true })">完了のみ</button>
<button on:click="set({ condition: false })">未完了のみ</button>
<script>
import { push, splice } from 'svelte-extras';
export default {
components: {
TodoListItem: './TodoListItem.html',
},
data() {
return {
title: '',
todos: [],
condition: null,
};
},
computed: {
filteredTodos({ todos, condition }) {
return condition !== null ? todos.filter(todo => todo.done === condition) : todos;
},
},
methods: {
push,
splice,
addTodo(title) {
this.push('todos', { title, done: false });
this.set({ title: '' });
},
toggleTodo({ todo, index }) {
this.splice('todos', index, 1, { ...todo, done: !todo.done });
},
},
};
</script>
ここでようやくJavaScriptが出てきました。
Svelteでは、script
タグ内にコンポーネントに関連するJavaScriptの処理を記述します。
components
プロパティには、使用する子コンポーネントを定義します。
ここでは先ほどのTodoListItemですね。
data
関数では、コンポーネントで使用するデータを初期化します。
ToDoを追加するためのtitle
、ToDoの一覧を保持するためのtodos
、完了/未完了で表示を切り替えるためのcondition
を定義しています。
computed
プロパティでは、他の値に依存して変化する値を定義します。
今回は完了/未完了で表示を切り替えたいので、condition
の値に連動して表示するToDoをフィルタリングするよう、ここで記述しています。
methods
プロパティでは、主にhtmlテンプレート内で呼び出す関数を定義します。
addTodo
は文字通り、ToDoを追加するための関数です。
単純に、todos
に新しいToDoを追加した後、title
を初期化しています。
Svelteでは、配列に要素を追加するのはsvelte-extras
のpush
関数で行います(35行目)。
また、単純な値の更新はset
関数を使います(36行目)。
この関数は「追加」ボタンが押されると呼び出されます。
toggleTodo
は、ToDoの完了/未完了状態を切り替えるための関数です。
5行目で、子コンポーネント(TodoListItem)からのイベントを受け取ると、この関数を呼ぶように記述しています。
最後にmain.jsを以下のように書き換えましょう。
import TodoList from './TodoList.html';
const todoList = new TodoList({
target: document.body,
});
export default todoList;
以下の画像のように表示されるはずです。
せっかくですので、色々いじって試してもらえればと思います。
終わりに
と、ここまでSvelteを触ってきましたが、Vueのシンタックスにかなり似ています。
なので、Vueを触ったことのある人であればかなり馴染みやすいのではないでしょうか。
ただ、Vueと同じ感覚で書いていると、割と色んなところでハマるな、といったのが自分の印象です。^^;
とはいえ面白いフレームワークだと思いますし、一度Svelteでちゃんとしたアプリも作ってみたいなー、と思いました。
今回のToDoリストでは売りのパフォーマンスの部分も全くわからないので。。。
また機会があればSvelteについて書いてみようと思います。
お読みいただきありがとうございました。