🏭

SvelteでTicTacToe

2022/12/23に公開

SvelteKit 1.0 🎉 効率的で無駄のない、研ぎ澄まされた Web 開発

VueとReactは触ったことがあるものの、Svelteがどんなものかを知らなかったので、とりあえずTicTacToeを作ってみました。

プロジェクト作成

npm create svelte@latest svelte-tictactoe -- --template svelte
cd svelte-tictactoe
npm install
npm run dev

ソースコード

四角形のボタンコンポーネント

/src/lib/square.svelte

<script>
  import { createEventDispatcher } from "svelte";
  export let value;
  export let number;
  const dispatch = createEventDispatcher();
  const changeValue = () => {
    dispatch("flip",{number});
  }
</script>

<button class="square" on:click|once={changeValue}>
  {value}
</button>

<style>
.square {
  border: solid black 2px;
  width:100px;
  height:100px;
  font-size: 32px;
}
</style>

<script>タグの中身は普通のJavaScriptです。
ただ、exportキーワードが特殊で、親のコンポーネントからの値を受けつける変数になります。
createEventDispatcher()は、親コンポーネントへイベントを送信するためのものです。
changeValue関数が呼び出されると、dispatchが動いて親コンポーネントにflipという名前のイベントが発火します。

<button>タグではon:click|onceで、クリックされたら呼ばれる関数を定めています。|onceとつけることで、一回だけしかそのイベントが起きなくなります。(便利!)

{}の中では、<script>内で宣言した変数や関数などを使用でき、ロジックも組むことが出来ます。

<style>の中身は普通のCSSです。

メインのコンポーネント

/src/Main.svelte

<script>
  import Square from './lib/Square.svelte'
  let squares = Array(9).fill("");
  let stepNumber = 0;
  let xIsNext = true;
  let winner = null;

  function calculateWinner() {
    const lines = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6]
    ];
    for (let i = 0; i < lines.length; i++) {
      const [a, b, c] = lines[i];
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return squares[a];
      }
    }
    return null;
  }

  function next(event){
    squares[event.detail.number] = xIsNext ? "X" : "O";
    xIsNext = !xIsNext;
    winner = calculateWinner();
  }
  
</script>

<main>
  <div class="status">
  {#if winner}
    Winner: {winner}
  {:else}
    Next player: {xIsNext ? "X" : "O"}
  {/if} 
  </div>
  <div class="board">
  {#each Array(9) as _, i}
    <Square value={squares[i]} number={i} on:flip={next}/>
  {/each}
  </div>
</main>

<style>
.board {
  display: grid;
  grid-template-columns: repeat(3, 100px)
}
</style>

<script><style>タグの中身は、それぞれほとんど普通のJSとCSSです。
importキーワードで他のコンポーネントをインポートすることができ、ここではSquareをインポートすることで、<Square/>タグが使用できるようになっています。

HTMLっぽい部分がとてもSvelte感がありますね。{#if}で条件分岐や{#each}で繰り返しが使えます。

完成品がこちら↓

感想

調べて触って1,2時間ぐらいですが、非常に分かりやすくコードも短くて済むのでコーディングしていて楽しかったです。
ReactやVueを学んだ時より『どうしてこう書くんだろう...?』が少なく、多少特殊な書き方もありますがすんなり飲み込めました。
ReactやVueと比較した際の技術的な違いによる利点について書けるほど理解はできてないですが、少しチュートリアルをしてみただけで、開発体験の一端を知れた気がするので、興味のある方は是非触ってみてください。

Discussion