svelte的一些基礎demo

歐陽碼農發表於2023-12-28

腳手架

Vite:vite是整合了svelte,初始化的時候選擇svelte就行了。

npm init vite

SvelteKit:底層基於vite的更上層框架,類似於nextjs。

npm create svelte@latest my-app
cd my-app
npm install
npm run dev

.svelte檔案結構

和vue類似svelte檔案是.svelte結尾的檔案,比如demo.svelte。程式碼結構:

<script>
  let name = 'hello world';
</script>

<div class="name">
  {name}
</div>

<style>
.name {
  color: red;
}
</style>

模版繫結

繫結變數

<script>
  let name = 'world';
</script>

<h1>Hello {name}!</h1>

繫結屬性

<script>
  let src = '/tutorial/image.gif';
  let name = '張三';
</script>

<img {src} alt="{name} dances.">

繫結事件

<script>
  let count = 0;

  function incrementCount() {
    count += 1;
  }
</script>

<button on:click={incrementCount}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

$:類似於vue的computed。例如:

<script>
  let count = 0;
    // 定義一個名字叫doubled的變數,當count的值改變時,doubled會改變。doubled變數時響應式的。
  $: doubled = count * 2;
    // 直接這樣寫d2不是響應式的。
  let d2 = count * 2;

    $: if (count >= 10) {
        alert('count is dangerously high!');
        count = 9;
    }

    $: {
        console.log('the count is ' + count);
        alert('I SAID THE COUNT IS ' + count);
    }

  function handleClick() {
    count += 1;
  }
</script>

<button on:click={handleClick}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

<p>{count} doubled is {doubled}</p>
<p>
  t2 is {d2}
</p>

為什麼d2變數不是響應式的,我們會在 svelte響應式原理裡面解釋。
if/else

	  <script>
	  	let user = { loggedIn: false };

	  	function toggle() {
	  		user.loggedIn = !user.loggedIn;
	  	}
	  </script>

	  <div>
	    {#if user.loggedIn}
	        <button on:click={toggle}>
	            Log out
	        </button>
	    {:else}
	        <button on:click={toggle}>
	            Log in
	        </button>
	    {/if}
	  </div>

each遍歷

<script>
  let cats = [
    { id: 'J---aiyznGQ', name: 'Keyboard Cat' },
    { id: 'z_AbfPXTKms', name: 'Maru' },
    { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
  ];
</script>

<h1>The Famous Cats of YouTube</h1>

<ul>
  {#each cats as { id, name }, i}
    <li><a target="_blank" href="https://www.youtube.com/watch?v={id}" rel="noreferrer">
      {i + 1}: {name}
    </a></li>
  {/each}
</ul>

await

<script>
  async function getRandomNumber() {
    const res = await fetch(`/tutorial/random-number`);
    const text = await res.text();

    if (res.ok) {
      return {val: text};
    } else {
      throw new Error(text);
    }
  }

  let promise = getRandomNumber();

  function handleClick() {
    promise = getRandomNumber();
  }
</script>

<button on:click={handleClick}>
  generate random number
</button>

{#await promise}
  <p>...waiting</p>
{:then res}
  <p>The number is {res.val}</p>
{:catch error}
  <p style="color: red">{error.message}</p>
{/await}

雙向資料流

<script>
  let name = 'world';
    $:
</script>

<input bind:value={name}>

<h1>Hello {name}!</h1>

元件

使用子元件和父子元件通訊
App.svelte

<script lang="ts">
  import Child from './child.svelte';

  var num = 1;
    var obj = {
      count: 1
    }

  function handleAdd() {
    num = num + 1;
        obj.count = obj.count + 1;
  }

    function handleReset(event) {
    num = event.detail.val;
    obj.count = event.detail.val;
  }
</script>

<div>
  我是父元件
  <button on:click={handleAdd}>add num</button>
    // 也支援...的語法
  <Child count={num} on:reset={handleReset} />
    <Child {...obj} on:reset={handleReset} />
</div>

Child.svelte

<script>
  import { createEventDispatcher } from 'svelte';
  export let count;

  const dispatch = createEventDispatcher();

  function handleReset() {
    dispatch('reset', {
      val: 0
    });
  }
</script>

<div>
  <p>我是子元件,count is {count}</p>
  <button on:click={handleReset}>reset count</button>
</div>

元件中使用雙向資料流
App.svelte

<script>
  import Child from './child.svelte';

  var name;
</script>

<p>
  name is {name}
</p>
<Child bind:name />

Child.svelte

<script>
  export let name;
</script>

<div>
  <input bind:value={name} />
</div>

插槽
App.svelte

<script>
  import Child from './child.svelte';
</script>

<Child>
  <p>i am from App</p>
  <p slot="tool">i am tool</p>
</Child>

Child.svelte

<div>
  <slot />
  <slot name="tool" />
</div>

生命週期

onMount、onDestroy、beforeUpdate、afterUpdate

<script>
  import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';

  onMount(() => {
    //...
  });

  onDestroy(() => {
    //...
  });

    beforeUpdate(() => {
    //...
  });

    afterUpdate(() => {
    //...
  });
</script>

<h1>Photo album</h1>

相關文章