Framework Svelte là gì và cách dùng nó?

Svelte là một trong số framework JavaScript “hot” nhất hiện tại. Dưới đây là mọi điều bạn cần biết về cách dùng framework Svelte.

Framework Svelte

Hướng dẫn sử dụng Svelte

Bạn sẽ thiết lập mọi thứ bằng công cụ build Vite. Mở terminal và chạy lệnh bên dưới theo thứ tự. Đặt tên dự án “svelte-app” (hoặc lựa chọn của bạn), chọn Svelte làm framework và đặt JavaScript làm biến.

yarn create vite
cd svelte-app
yarn
yarn dev

Mở dự án trong trình chỉnh sửa code, xóa thư mục lib và nội dung của file app.css và App.svelte.

Khác biệt giữa Svelte và React

DOM là một cấu trúc dạng cây được tạo từ HTML của trang web. Nó hiện mối quan hệ giữa các phần tử khác nhau trong code tạo nên trang này.

Sự khác biệt giữa Svelte và React

Khác React dùng DOM ảo, Svelte là một trình biên dịch biết được mọi thứ trong ứng dụng thay đổi như thế nào lúc trong thời gian build. Vì Svelte hoạt động ở giai đoạn build nên nó mang tới VanillaJS hiệu suất cao và được tối ưu hóa.

Khả năng phản ứng và hiệu ứng động trong Svelte

Cấu trúc của hầu hết ứng dụng Svelte được minh họa như bên dưới. Bạn có thể chọn không bao gồm các thẻ style, chỉ để lại script và markup:

<script>
// Scripting Logic
</script>

<!-- Markup -->

<style>
/* Scoped Styling */
</style>

Trong Svelte, khả năng phản ứng dựa trên sự phân công. Hãy xem code sau:

<script>
    let count = 0;
    const handleClick = () => {
        count += 2;
    }
</script>

<main>
You have clicked: 
<button on:click={handleClick}>
     {count} {count === 1 ? 'time' : 'times'}
</button>
</main>

Thẻ script xác định biến count và hàm handleClick tăng số đếm lên 2. Phần tử main có một nút bấm với lệnh on:click để chạy hàm handleClick. Button update khi count thay đổi.

Svelte khiến việc tạo hiệu ứng động cho các phần tử trở nên dễ dàng. Hãy tưởng tượng bạn có một bức ảnh với chiều rộng có thể được điều chỉnh bằng cách nhấn vào một nút bấm, tiện ích tweened của mô đun svelte/motion có thể được dùng để đạt hiệu ứng này.

<script>
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
let src="https://images.pexels.com/photos/718752/pexels-photo-718752.jpeg";
    
    let size=tweened(30, {
        duration: 900,
        easing: cubicOut
    })
</script>

<button on:click={()=>size.set($size+30)}>
    Increase Photo Size
</button>
<button on:click={()=>size.set($size-30)}>
    Decrease Photo Size
</button>
<br />
<img src={src} width={$size} />

Code này dùng tweened trong giao tiếp và tạo hiệu ứng cho thành phần. Nới lỏng cubicOut để tạo một hiệu ứng động mượt mà. Size.set(…) trả về đã xử lý sau khi tween được hoàn thiện.

Xây dựng một app đơn giản với Svelte

Giờ hãy xem chức năng để xác thực các mục trước khi chúng được thêm vào danh sách cần làm, loại bỏ mục, cảnh báo người dùng nếu input không hợp lệ, đồng thời lưu danh sách cần làm trong ổ lưu trữ nội bộ.

Tạo file src/components/Item.svelte và trong App.svelte, xác định phần tử <script> import Item từ ./components/Item.svelte. Item được dùng để kết xuất từng mục to-do.

<script>
  import Item from "./components/Item.svelte";
</script>

Xác định một mảng tên todo và bốn biến cụ thể là: alertMessage, errorMessage, duplicateMessage, và successMessage.

  import Item from "./components/Item.svelte";
  let todo = [];
  let errorMessage = "Item cannot be empty!";
  let duplicateMessage = "Item already added!";
  let successMessage = "Item has been added and list updated!";
  let alertMessage;

Trong phần markup, bên dưới script, tạo một phần tử chính làm điểm nhập. Bên trong nó, tạo div khác với một phần tử h6 cùng class “alert hidden”. Phần tử này hiện thông báo thành công dựa trên biến alertMessage.

<main>
<div class="app">
<h6 class="alert hidden">{alertMessage}</h6>
</div>
</main>

Tạo một heading h1 "Svelte To-Do List", sau đó thêm phần tử form với input type “text”. Bạn sẽ có một placeholder với chiều dài tối đa là 32 ký tự, một nút gửi với lệnh on:submit trên biểu mẫu để kích hoạt hàm addToDo, với giá trị input là tham số.

  <form on:submit|preventDefault={() =>
          addTodo(document.querySelector("input").value)}>
        <div>
          <input type="text" placeholder="Enter Something" maxlength="39" />
          <button type="submit">Add</button>
        </div>
      </form>

Tạo div “todo-container “ bên trong div “app”. Xuất div “todo” nếu mảng todo không trống, nếu không, xuất div với text "[Empty]".

Lặp lại mảng todo trong dive “todo”, xuất thành phần Item nhận thuộc tính: "item", "done", "removeTodoHandler" và "updateTodoHandler".

<div class="todo-container">
      {#if todo.length}
        <div class="todo">
          {#each todo as { item, done } (item)}
            <Item
              {item}
              {done}
              removeTodoHandler={removeTodo}
              updateTodoHandler={updateTodo}
            />
          {/each}
        </div>
      {:else}
        <div>[Empty]</div>
      {/if}
    </div>
  </div>

Trước khi tiếp tục xác định logic cho ứng dụng này, hãy đặt kiểu phạm vi cho tin nhắn cảnh báo. Để làm việc này, xác định phần tử style bên dưới markup và thêm như sau:

  :global(.alert) {
    padding: 10px;
    color: white;
    position: absolute;
    left: 50%;
    top: -25px;
    transform: translateX(-50%);
    width: max-content;
  }
  :global(.error) {
    background-color: rgba(255, 0, 0, 0.6);
  }
  :global(.success) {
    background-color: rgba(0, 128, 0, 0.6);
  }
  :global(.hidden) {
    display: none;
  }

Code này định nghĩa kiểu cho box thông báo dựa trên kiểu alert bằng trình chỉnh sửa :global(). Trong thẻ script, bạn có 5 hàm: validate(), displayAlert(), addTodo(), removeTodo(), updateTodo().

Mỗi hàm, ngoại trừ displayAlert, lấy một tham số mục. Hàm xác thực kiểm tra một chuỗi trống hoặc mục trùng lặp trong danh sách cần làm hiện tại (được lưu trong mảng allItems).

  function validate(item) {
    let allItems = todo.map((x) => x.item);
    if (item.length === 0) {
      return "error";
    } else if (allItems.includes(item.trimEnd().trimStart())) {
      return "duplicate";
    } else {
      return "success";
    }
  }

Hàm displayAlert() hiện cảnh báo kèm kiểu (error, duplicate, hoặc success). Nó đặt thông báo phù hợp và các kiểu dựa trên type và ẩn cảnh báo sau 2 giây.

  function displayAlert(type) {
    let alert = document.querySelector(".alert");
    alert.classList.remove("hidden");
    if (type === "error") {
      alertMessage = errorMessage;
      alert.classList.add("error");
    } else if (type === "duplicate") {
      alert.classList.add("error");
      alertMessage = duplicateMessage;
    } else {
      alert.classList.add("success");
      alertMessage = successMessage;
    }
    setTimeout(() => {
      alert.className = "alert hidden";
    }, 2000);
  }

updateTodo() thêm một mục mới vào mảng todo sau khi xác thực. Nếu mục này hợp lệ, nó được thêm vào mảng todo, trường nhập được xóa và thông báo thành công xuất hiện.

  function addTodo(item) {
    let response = validate(item);
    if (response === "error") {
      displayAlert("error");
    } else if (response === "duplicate") {
      displayAlert("duplicate");
    } else {
      todo = [{ item: item.trimEnd().trimStart(), done: false }, ...todo];
      console.log(todo);
      localStorage.setItem("todo", JSON.stringify(todo));
      document.querySelector("input").value = "";
      displayAlert("success");
    }
  }

updateTodo() mở trạng thái “done” của mảng todo, còn removeTodo() loại bỏ một mục cụ thể khởi mảng todo.

  function updateTodo(item) {
    let target = todo.findIndex((x) => x.item === item);
    todo[target].done = !todo[target].done;
  }
  
  function removeTodo(item) {
    todo = todo.filter((x) => x.item !== item);
  }

Giờ tới file Item.svelte, xác định phần tử script xuất thuộc tính item, removeTodoHandler, done, và updateTodoHandler. Xác định một biến tên hover chứa giá trị boolean, false.

<script>
    export let item;
    export let removeTodoHandler;
    export let done;
    export let updateTodoHandler;
    let hover = false;
</script>

Trong phần markup, div được xác định bằng một class động dựa trên giá trị của biến “done”. Nếu “done” đúng, class “strike” được thêm, áp dụng CSS: line-through text-decoration để biểu thị hoàn thành. Hai lệnh thành phần, on:mouseenter" và "on:mouseleave," được bao gồm để bật trạng thái hover.

<div class="item {done ? 'strike' : ''}"
    on:mouseenter={() => (hover = true)}
    on:mouseleave={() => (hover = false)}>

</div>

Phần tử cha chứa hai thành phần: một div (hiện ô tích và mục todo) và một nút bấm được xuất theo điều kiện khi trạng thái trỏ là true. Ô tích được liên kết với biến “done” và kích hoạt hàm “updateTodoHandler” khi được thay đổi.

 <div>
        <input
            class="done"
            type="checkbox"
            bind:checked={done}
            on:change={() => updateTodoHandler(item)}/>
        <span>{item}</span>
    </div>

    {#if hover}
        <button class="delete" on:click={() => removeTodoHandler(item)}
            >Remove
        </button>
    {/if}
</div>

Thế là xong! Bạn đã tạo thành công một ứng dụng lên danh sách việc cần làm đa năng rồi đấy.

App todo này tạo, loại bỏ và đánh dấu các mục đã hoàn thành nhưng tất cả dữ liệu đó đều biến mất khi trang được làm mới.

Khắc phục vấn đề này bằng cách thêm bộ nhớ. Để giữ lại dữ liệu khi làm mới trang, chỉnh sửa mảng todo như sau:

let todo=JSON.parse(localStorage.getItem("todo")) || [];

Code này truy xuất và phân tích từ khóa “todo” từ bộ nhớ cục bộ của trình duyệt. Nếu giá trị này không đúng, nó mặc định là một mảng trống.

Tiếp theo, thêm dòng sau vào các hàm addTodo(), updateTodo(), removeTodo().

localStorage.setItem("todo", JSON.stringify(todo));

Hành động trên lưu mảng todo trong bộ nhớ nội bộ, đảm bảo tính bền vững của dữ liệu.

Nhìn chung, Svelte là một lựa chọn thay thế tuyệt vời cho React. Hãy thử và xem Svelte có thể đem lại cho bạn những điều gì nhé!

Thứ Tư, 31/05/2023 16:51
4,33 👨 345
0 Bình luận
Sắp xếp theo