I. Cài đặt môi trường phát triển

Cài đặt công cụ phát triển

Để phát triển ứng dụng với Svelte cần cài đặt Node.js

Sau khi cài xong Node.js, cần cài thêm công cụ degit: từ cửa sổ command ,gõ lệnh:

npm install -g degit
Tạo mới ứng dụng

Từ cửa sổ command gõ lệnh:

npx degit sveltejs/template my-app
cd my-app
npm install
Chạy ứng dụng

Để chạy ứng dụng, mở cửa sổ command tại thư mục gốc của ứng dụng và chạy lệnh:

npm run dev

Truy nhập ứng dụng tại địa chỉ http://127.0.0.1:8080

Cài đặt IDE:

Nên sử dụng Visual Studio Code với Svelte Plugin:


II. Một số chức năng thông dụng trong svelte

Hiển thị dữ liệu từ javascript lên DOM

Các biến khai báo trong phần script của Svelte có thể được truy xuất trong phần HTML DOM. Để phân biệt với các giá trị text thông thường của HTML, biến javascript được đặt trong cặp dấu ngoặc nhọn.

Ví dụ:

      
        <script>
          let name = "Nguyen Van A";
        </script>
        <main>
          <div>Hello {name}</div>
        </main>
      
Chạy thử chương trình

Biến javascript cũng có thể dùng làm thuộc tính cho các thẻ HTML, ví dụ:

      
        <!-- File: App.svelte-->

        <script>
          let name = "Nguyen Van A";
          let gender = "male";
          let city = "HANOI";
          let married = true;
        </script>

        <main>
          <div>Name: <input value={name} /></div>

          <div>
            Gender:
            <input type="radio" checked={gender == "male"} name="gender" /> Male
            <input type="radio" checked={gender == "female"} name="gender" /> Female
          </div>

          <div>
            Address:
            <select value={city}>
              <option value="HANOI">Ha Noi</option>
              <option value="HCMCity">HCM City</option>
            </select>
          </div>
          
          <div>Married: <input type="checkbox" checked={married} /> </div>

        </main>
      
Chạy thử chương trình

Component

Tương tự các frame Frontend khác, Svelte dùng Component để chia ứng dụng thành các phần nhỏ. Trong Svelte, mỗi Component tương ứng với một file với tên mở rộng .svelte.

Ví dụ: Trong thư mục src của project tạo thư mục components và thêm mới các file như bên dưới:

      
        <!-- File: App.svelte-->

        <script>
          import Header from "./components/Header.svelte";
          import Body from "./components/Body.svelte";
        </script>
        
        <main>
          <Header title="Title" />
          <Body/>
        </main>
      
      
        <!-- File: components/Header.svelte-->

        <script>
          export let title;
        </script>
        
        <main>
          <h1>{title}</h1>
        </main>
      

      
        <!-- File: components/Body.svelte-->

        <main>
          <p>Line 1</p>
          <p>Line 2</p>
        </main>
      
Chạy thử chương trình

Mỗi component chứa một phần của ứng dụng: Header, Body, ..., file App.svelte import các component và ghép lại thành ứng dụng đầy đủ:

<main>
  <Header title="Title" />
  <Body />
</main>

Thuộc tính của Component:

Thuộc tính dùng để truyền dữ liệu từ ứng dụng (hoăc Component lớn) sang các Component nhỏ hơn. Thuộc tính của các Component được viết giống như cách viết thuộc tính của các thẻ HTML.

Ví dụ, trong file App.svelte, dữ liệu được được truyền sang cho Component Header theo cú pháp:

<Header title="Title" />

Thuộc tính của Component cũng có thể nhận giá trị là một biểu thức javascript, khi đó giá trị được đặt trong cặp ngoặc nhọn {}:

<Header title={"Hello " + username} />

Trong file Header.svelte, dữ liệu được lấy ra bằng cách thêm từ khoá export trước khai báo của biến title trong phần script:

<script>
  export let title;
</script>

Sau đó, trong phần html của Header.svelte, biến title này được dùng để hiển thị nội dung:

<h1>{title}</h1>

Xử lý sự kiện

Tương tự như javascript thông thường, có thể gắn các hàm xử lý sự kiện cho các phần tử html.

Hàm xử lý sự kiện của Svelte được bắt đầu với ký hiện on: (on:change, on:click, ...) để phân biệt với các hàm xử lý sự kiện của javascript.

Ví dụ:

      
        <!-- File: App.svelte-->
        
        <script>
          function btnHandler() {
            alert("Click");
          }
        
          function changeHandler(event) {
            alert(event.target.value);
          }
        </script>
        
        <main>
          <input on:change={changeHandler} />
          <button on:click={btnHandler}>Ok</button>
        </main>
      
Chạy thử chương trình

Thuộc tính event.target.value chứa dữ liệu của phần tử khi xảy ra sự kiện on:change:

function changeHandler(event) {
  alert(event.target.value);
}

Dùng on:change để lấy lấy dữ liệu người dùng

Để lấy dữ liệu người dùng nhập vào các phần tử control (input, textarea, select, ...), sử dụng sự kiện on:change của các phần tử để cập nhật dữ liệu vào các biến Javascript.

Lấy dữ liệu từ input/textarea:
      
        <!-- File: App.svelte-->

        <script>
          let text = "";
        </script>
        <main>
          <input
            placeholder="Enter some text..."
            value={text}
            on:change={(event) => text = event.target.value}
          />
          <br />
          {text}
        </main>
      
Chạy thử chương trình

Lấy dữ liệu từ select:
      
        <!-- File: App.svelte-->

        <script>
          let gender = "";
        </script>
        <main>
          <select
            value={gender}
            on:change={(event) => gender = event.target.value}
          >
            <option value="">--Choose your gender---</option>
            <option value="M">Male</option>
            <option value="F">Female</option>
            <option value="O">Other</option>
          </select>
          <br />
          {gender}
        </main>
      
Chạy thử chương trình

Lấy dữ liệu từ checkbox:
      
        <script>
          let agree = false;
        </script>
        
        <main>
          <input
            type="checkbox"
            checked={agree}
            on:change={event => agree = event.target.checked}
          />{" "}
          Agree with terms & conditions
          <br />
          {agree ? "Checked" : "Unchecked"}
        </main>
      
Chạy thử chương trình

Lấy dữ liệu từ radiobox:
      
        <script>
          let gender = "";
        </script>
        
        <main>
          Your gender:
          <input
            type="radio"
            name="gender"
            value="M"
            checked={gender === "M"}
            on:change={(event) => gender = event.target.value}
          />{" "}
          Male
          <input
            type="radio"
            name="gender"
            value="F"
            checked={gender === "F"}
            on:change={(event) => gender = event.target.value}
          />{" "}
          Female
          <br />
          {gender}
        </main>
      
Chạy thử chương trình

Hiện thị theo điều kiện (if-else)

Cú pháp if được dùng để hiện/ẩn một block theo một điều kiện logic:

{#if <dieu_kien_logic>}
  <block1>
{:else}
  <block2>
{/if}

Ví dụ:

      
        <!-- File: App.svelte-->
        <script>
          let show = true;
          const message = "Hello world!";
        </script>
        
        <main>
          {#if show}
            {message}
            <button 
              on:click={() => show=false}
            >
              Hide
            </button>
          {:else}
            <button 
              on:click={() => show=true}
            >
              Show
            </button>
          {/if}
        </main>
      
Chạy thử chương trình

Hiện thị danh sách (vòng lặp for)

Vòng lặp for được dùng để hiển thị dữ liệu ra các danh sách/bảng dữ liệu:

{#each item_list as item, index}
  <!-- render item -->
{/each}

Ví dụ:

      
        <!-- File: App.svelte-->

        <script>
          const productList = [
            { code: "IPX", name: "IPhone X", price: 10.5 },
            { code: "IP11", name: "IPhone 11", price: 11.5 },
            { code: "IP12", name: "IPhone 12", price: 12.5 }
          ];
        </script>
        
        
        <main>
          <table border="1">
            <thead>
              <tr>
                <th>Code</th>
                <th>Name</th>
                <th>Price</th>
              </tr>
            </thead>
            <tbody>
              {#each productList as product}
                <tr>
                  <td>{product.code}</td>
                  <td>{product.name}</td>
                  <td>{product.price} M</td>
                </tr>
              {/each}
            </tbody>
          </table>
        </main>
      
Chạy thử chương trình

Router

Một ứng dụng thực tế thường có nhiều trang thành phần (tương tự như các file trong một thư mục)

Router được sử dụng để điều hướng truy nhập các trang của ứng dụng theo địa chỉ link (URL).

Để sử dụng router với Svelte, cần cài đặt thêm thư viện svelte-navigator: mở cửa sổ command trong thư mục gốc của project và gõ lệnh:

npm install svelte-navigator

Sau khi cài đặt xong, mở file package.json trong thư mục gốc của project và kiểm tra để đảm bảo thư viện đã có trong danh sách dependencies của project:

Cấu hình router:

Tạo thư mục pages trong thư mục gốc ứng dụng, sau đó tạo 2 file Page1.sveltePage2.svelte trong thư mục này

Nhập nội dung các file như dưới đây:

      
        <!-- File: App.svelte-->
        <script>
          import { Router, Route, Link } from "svelte-navigator";
          import Page1 from "./pages/Page1.svelte";
          import Page2 from "./pages/Page2.svelte";
        </script>
        
        <Router>
          <header>
            <nav>
              <Link to="/">Page 1</Link>
              <Link to="/page-2">Page 2</Link>
            </nav>
          </header>
          <main>
            <Route path="/">
              <Page1/>
            </Route>
            <Route path="/page-2">
              <Page2/>
            </Route>
          </main>
        </Router>
      
      
        <!-- File: pages/Page1.svelte-->
        <main>
          <h1>Page 1</h1>
          Page 1 Content
        </main>
      
      
        <!-- File: pages/Page2.svelte-->
        <main>
          <h1>Page 2</h1>
          Page 2 Content
        </main>
      
    

Khi chạy ứng dụng, giao diện sẽ có dạng như hình bên dưới:

Phía trên cùng của ứng dụng là navigator với các link để chuyển trang, phía dưới là nội dung trang được chọn.

Khi click vào các link trên navigator thì trang tương ứng sẽ được hiển thị. Ngoài ra, trên thanh địa chỉ trình duyệt, địa chỉ trang cũng thay đổi theo.

Store

Store được dùng để trao đổi dữ liệu giữa các component

Quá trình trao đổi dữ liệu giữa Component cha và Component con được thực hiện qua thuộc tính ( xem phần Component.). Việc trao đổi giữa liệu giữa các Component ở các cấp khác nhau không thể thực hiện theo cách này.

Để khắc phục vấn đề này, store giúp trao đổi dữ liệu giữa 2 component bất kỳ theo mô hình sau:

Khi có sự kiện ở Component 1, action được thực hiện (commit) để làm thay đổi trạng thái của store. Component 2 đăng ký theo dõi sự thay đổi này (subscribe) và cập nhật lại hiển thị khi trạng thái thay đổi.

Cấu hình store:

Tạo mới file store.js trong thư mục src của project với nội dung như sau:

      
        // store.js

        import { writable } from "svelte/store";

        export const state1 = writable("initialState1");
        export const state2 = writable("initialState2");
        //...
      
    

Các biến state1, state2, ... là các biến trạng thái chia sẻ chung cho tất cả các Component, còn initialState1, initialState2, ... là các giá trị khởi tạo cho các biến này.

Sử dụng Store:

Việc sử dụng Store gồm 2 phần: Thay đổi giá trị biến trạng thái của store (commit action) và đăng ký theo dõi sự thay đổi của các biến trạng thái.

Thay đổi biến trạng thái của Store:

Để thay đổi trạng thái của store, sử dụng theo cách sau:

      
        import { state1 } from "./store";
        function commitAction() {
          state1.update(val => new_val);
        }
      
    

Sử dụng hàm update của biến trạng thái để làm thay đổi giá trị biến đó. Hàm update có tham số là một hàm với đầu vào là giá trị hiện tại của biến trạng thái và kết quả trả về là giá trị mới của biến trạng thái.

state1.update(val => new_val);

Đăng ký theo dõi thay đổi của các biến trạng thái

Khi một biến trạng thái thay đổi giá trị, một số Component cần phải hiển thị lại (re-render). Để thực hiện việc này, Component cần đăng ký theo dõi sự thay đổi giá trị của biến trạng thái đó. Cách thực hiện như sau:

      
        import { state1 } from "./store";
        let localState1;
        state1.subscribe(val => localState1 = val);
      
    

Component cần khai báo một biến để chứa trạng thái tạm thời (local state), sau đó dùng hàm subscribe của biến trạng thái của store để update trạng thái local khi có sự thay đổi.

Biến trạng thái local sau đó được dùng để hiển thị trong phần HTML của component

      
        <main>
          ...
          <div>{localState1}</div>
          ...
        </main>
      
    
Ví dụ: Counter app

Ứng dụng counter có một biến trạng thái (ban đầu bằng 0), khi người dùng click vào button tăng thì counter tăng thêm 1, khi người dùng click vào button giảm thì counter giảm đi 1.

      
        // File: store.js

        import { writable } from "svelte/store";
        export const counter = writable(0);
      
      
        <script>
          <!-- File: App.svelte -->

          import { counter } from "./store";
          
          function increase() {
            counter.update(val => val+1);
          }
        
          function decrease() {
            counter.update(val => val-1);
          }
          let counterValue;
        
          counter.subscribe(val => counterValue = val);
        </script>
        
        <main>
          Counter: {counterValue} 
          <button on:click={increase}>+</button>
          <button on:click={decrease}>-</button>
        </main>
      
    

Khi chạy ứng dụng, kết quả sẽ như sau: