Svelteをwebpackで動かしてTODOリストを作成してみた

私はsvelteに最近さわってみた者です。間違っていたら指摘お願いいたしますm(_ _)m

私が作成したtodoリストのサンプル

- https://github.com/okumurakengo/svelte-todo-list

---

参考

- [Vue使いなら秒で覚えられるSvelte入門 - Qiita](https://qiita.com/POPOPON/items/3522c48765b6e9439bde)
- [Learn Svelte 3 by building a Todo List App](https://freshman.tech/svelte-todo/)

`.svelte`ファイルのシンタックスハイライトは`svelte-vscode`を使用して開発させていただきました

- https://github.com/UnwrittenFun/svelte-vscode

# Install

```bash
yarn add -D svelte svelte-loader css-loader mini-css-extract-plugin webpack webpack-cli webpack-dev-server
```

- `svelte`
- `svelte-loader`
    - svelteコンポーネント用のローダー
- `css-loader`
    - cssローダー
- `mini-css-extract-plugin`
    - cssを抽出できるプラグイン

# Hello World!

`webpack.config.js`はこちらを参考にしました

- https://github.com/sveltejs/template-webpack
- https://github.com/sveltejs/svelte-loader

```webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    mode: process.env.NODE_ENV || "development",
    module: {
        rules: [
            {
                test: /\.svelte$/,
                use: {
                    loader: "svelte-loader",
                    options: {
                        // tureにすることで、
                        // svelteファイルの<style>タグをのcssを
                        // 「test: /\.css$/」のフローでコンパイルできる
                        emitCss: true,
                    }
                },
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                ],
            },
        ]
    },
    resolve: {
        extensions: [".mjs", ".js", ".svelte"],
    },
    plugins: [
        // 出力する際のファイル名を指定する
        new MiniCssExtractPlugin({ filename: "[name].css" }),
    ],
    devServer: {
        port: 9000,
        contentBase: "./",
        publicPath: "/dist/",
        open: true
    }
};
```

```src/index.js
import App from "./App";

const app = new App({
	target: document.body,
});

export default app;
```

```html:src/App.svelte
<script>
  let value = "world";
</script>

<style>
  h1 {
    color: purple;
  }
</style>

<h1>Hello {value} !</h1>
```

```index.html
<!DOCTYPE html>
<meta charset=UTF-8>
<title>Document</title>
<link rel=stylesheet href=dist/main.css>
<script src=dist/main.js defer></script>
```

```bash
yarn webpack-dev-server #http://localhost:9000/で確認できる
```

<img width="612" alt="Screen Shot 2019-07-22 at 23.20.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/65c81cbc-d90b-040c-9870-2c10f5f76448.png">

# TODOリスト作成

```html:src/App.svelte
<script>
  import { afterUpdate } from "svelte";
  afterUpdate(() => {
    document.querySelector(".js-todo-input").focus();
  });

  let todoItems = [];
  let newTodo = "";

  function addTodo() {
    newTodo = newTodo.trim();
    if (!newTodo) return;

    todoItems = [...todoItems, { text: newTodo, complete: false }];
    newTodo = "";
  }

  function toggleDone(index) {
    todoItems[index].complete = !todoItems[index].complete;
  }

  function removeTodo(index) {
    todoItems = todoItems.filter((_, i) => i !== index);
  }

  let value = "world";
</script>

<style>
  h1 {
    color: purple;
  }

  .done {
    text-decoration: line-through;
  }

  .delete {
    color: #777;
    text-decoration: none;
  }
</style>

<h1>Hello {value} !</h1>
<form on:submit|preventDefault={addTodo}>
  <input type="text" class="js-todo-input" bind:value={newTodo} />
  <button type="submit">Add Todo</button>
</form>
<ul>
  {#each todoItems as todo, index}
    <li>
      <input
        id={index}
        type="checkbox"
        bind:checked={todo.complete}
        on:click={() => toggleDone(index)} />
      <span class={todo.complete ? 'done' : ''}>{todo.text}</span>
      <a
        href="#hoge"
        class="delete"
        on:click|preventDefault={() => removeTodo(index)}>
        [x]
      </a>
    </li>
  {/each}
</ul>
```

![ScxYDiC4eG.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/af4d039c-eb11-c844-3b6a-3dd499c81128.gif)

TODOリストを作成することができました。最後まで読んでいただいてありがとうございました。m(_ _)m