Để 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:
Từ cửa sổ command gõ lệnh:
Để 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:
Truy nhập ứng dụng tại địa chỉ http://127.0.0.1:8080
Nên sử dụng Visual Studio Code với Svelte Plugin:
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
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 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>
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);
}
Để 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.
<!-- 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
<!-- 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
<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
<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
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
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
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:
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:
Tạo thư mục pages trong thư mục gốc ứng dụng, sau đó tạo 2 file Page1.svelte và Page2.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 đượ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.
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.
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);
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>
Ứ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: