🦔
SvelteでTodoをやってみるだけの回
はじめに
Svelteやってみたいが何やろうってことで、まずはTodoを作ってみるだけの、ほんとにそれだけの回
Hello Todo!
コード
Todo.svelte
とりあえずこれだけでなんとなくできたので貼っておきます[1]
Todo.svelte
<script>
let newTask = "";
let todos = [];
let newId = () => { return Date.now().toString(36) }
function add(task) {
todos = [...todos, {id: newId(), name: task, done: false}] // ❶
}
function done(id) {
console.log('done called')
let result = todos.map(todo => {
if (todo.id == id){ todo.done = true }
return todo
});
todos = result; // ❷
}
$: activeTodos = todos.filter(function(todo){ // ❸
return (todo.done == false)
});
</script>
<main>
<h1>HELLO TODO!</h1>
<div class="container">
<form>
<div class="row">
<div class="two-thirds column">
<input class="u-full-width" type="text" placeholder="Add new task" bind:value={newTask}>
</div>
<div class="one-third column"><input type="button" value="add" on:click={add(newTask)}></div>
</div>
</form>
{#if activeTodos.length === 0} <!-- ❹ -->
<h3>YOU HAVE NO TASK!</h3>
{:else}
<table class="u-full-width">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{#each activeTodos as todo} <!-- ❺ -->
<tr>
<td>{todo.id}</td>
<td>{todo.name}</td>
<td><input type="button" value="done!" on:click={done(todo.id)}></td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
</main>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
}
h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
margin-bottom: 1.5em;
}
h3 {
color: gray;
text-transform: uppercase;
font-size: 2em;
font-weight: 150;
margin-top: 3.5em;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>
- この
todos = [...todos, {id: newId(), name: task, done: false}]
はイディオム的に使うと良い。Svelteでリアクティブな動作をさせるには条件があるようで[2]、たとえばtodo.push({id: newId(), name: task, done: false})
だとリアクティブにならず、テーブルは更新されない - これも❶と同様にリアクティブにするために代入している
-
$:
のラベルをつけることで、リアクティブに再計算される。つまりtodos
が変更されるとactiveTodos
も再計算される - テンプレートの中で
if
分が使えたり -
each
でループしたり
main.js
Todo.svelte
をmain.js
側でimport
している
main.js
import Todo from './Todo.svelte';
const app = new Todo({
target: document.body,
});
export default app;
index.html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<title>Todo</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body></body>
</html>
こんだけ。CSSはskelton.css
もつかっています
感想
Svelteは思ったよりVueっぽいぞ。Vueのシングルファイルコンポーネントそのままに思える。Vueやってた人は違和感なく入れると思う。また、一方でVueよりも生のJavascriptを触っている感が味わえてそこがまたよい。
Discussion