Miền ứng dụng
Để thể hiện cách lập trình ứng dụng nhỏ được áp dụng cho một ứng dụng web, tôi cần một ý tưởng ứng dụng nhỏ nhưng đầy đủ. Đào tạo ngắt quãng cường độ cao (HIIT) là một chiến lược tập luyện tim mạch gồm các nhóm xen kẽ gồm các bài tập kỵ khí có cường độ cao trong thời gian ngắn và giai đoạn phục hồi ít có cường độ cao hơn. Nhiều bài tập cường độ cao ngắt quãng (HIIT) sử dụng đồng hồ tính giờ HIIT, chẳng hạn như phiên trực tuyến kéo dài 30 phút này trên kênh YouTube của The Body Coach TV.
![Buổi luyện tập trực tuyến Cardio ở cường độ cao với đồng hồ hẹn giờ màu xanh lục có cường độ cao.](https://web.dev/static/articles/mini-apps/mini-app-example-project/image/hiit-training-online-sess-ed5b035be1093.png?authuser=5&hl=vi)
![Buổi luyện tập trực tuyến cường độ cao ngắt quãng (HIIT) có đồng hồ hẹn giờ màu đỏ ở cường độ thấp.](https://web.dev/static/articles/mini-apps/mini-app-example-project/image/hiit-training-online-sess-a0dd5340756f1.png?authuser=5&hl=vi)
Ứng dụng ví dụ về HIIT Time
Trong chương này, tôi đã xây dựng một ví dụ cơ bản về ứng dụng bộ tính giờ HIIT có tên là "HIIT Time" cho phép người dùng xác định và quản lý nhiều đồng hồ hẹn giờ khác nhau, luôn bao gồm khoảng thời gian có cường độ cao và thấp, sau đó chọn một trong số đó cho phiên huấn luyện. Đây là một ứng dụng thích ứng có thanh điều hướng, thanh thẻ và 3 trang:
- Bài tập thể dục: Trang hoạt động trong một bài tập thể dục. Dịch vụ này cho phép người dùng chọn một trong các đồng hồ hẹn giờ và có 3 vòng tiến trình: số lượng bộ, thời gian hoạt động và thời gian nghỉ.
- Hẹn giờ: Quản lý các đồng hồ hẹn giờ hiện có và cho phép người dùng tạo đồng hồ hẹn giờ mới.
- Lựa chọn ưu tiên: Cho phép bật/tắt hiệu ứng âm thanh và đầu ra bằng giọng nói, cũng như chọn ngôn ngữ và giao diện.
Các ảnh chụp màn hình sau đây cho thấy ấn tượng về ứng dụng.
Cấu trúc ứng dụng
Như trình bày ở trên, ứng dụng bao gồm một thanh điều hướng, một thanh thẻ và 3 trang được sắp xếp theo bố cục lưới.
Thanh điều hướng và thanh thẻ được nhận dạng dưới dạng iframe với vùng chứa <div>
ở giữa chúng với 3 iframe khác cho các trang, trong đó một iframe luôn hiển thị và phụ thuộc vào lựa chọn đang hoạt động trong thanh thẻ.
Iframe cuối cùng trỏ đến about:blank
phân phát cho các trang trong ứng dụng được tạo động. Các trang này cần thiết để sửa đổi bộ tính giờ hiện tại hoặc tạo bộ tính giờ mới.
Tôi gọi mẫu này là ứng dụng một trang nhiều trang (MPSPA).
![Chế độ xem cấu trúc HTML của ứng dụng trong Công cụ của Chrome cho thấy cấu trúc này bao gồm sáu iframe: một iframe cho thanh điều hướng, một cho thanh thẻ và ba iframe cho mỗi trang của ứng dụng với iframe cho phần giữ chỗ cuối cùng cho các trang động.](https://web.dev/static/articles/mini-apps/mini-app-example-project/image/chrome-devtools-view-the-9da043317ba5b.png?authuser=5&hl=vi)
Đánh dấu lit-html dựa trên thành phần
Cấu trúc của mỗi trang được thực hiện dưới dạng lit-html scaffold (giàn giáo) được đánh giá động trong thời gian chạy.
Đối với nền trên lit-html, đây là một thư viện mẫu HTML hiệu quả, sinh động và có thể mở rộng cho JavaScript.
Bằng cách sử dụng trực tiếp API này trong các tệp HTML, mô hình lập trình trí tuệ được định hướng trực tiếp vào đầu ra.
Là một lập trình viên, bạn viết mẫu về kết quả cuối cùng sẽ trông như thế nào, sau đó lit-html tự động lấp đầy các khoảng trống dựa trên dữ liệu của bạn và kết nối các trình nghe sự kiện.
Ứng dụng sử dụng các phần tử tuỳ chỉnh của bên thứ ba như <sl-progress-ring>
của Shoele hoặc một phần tử tuỳ chỉnh tự triển khai có tên là <human-duration>
.
Vì các phần tử tuỳ chỉnh có API khai báo (ví dụ: thuộc tính percentage
của vòng tròn tiến trình), nên chúng hoạt động hiệu quả cùng với lit-html, như bạn có thể thấy trong danh sách dưới đây.
<div>
<button class="start" @click="${eventHandlers.start}" type="button">
${strings.START}
</button>
<button class="pause" @click="${eventHandlers.pause}" type="button">
${strings.PAUSE}
</button>
<button class="reset" @click="${eventHandlers.reset}" type="button">
${strings.RESET}
</button>
</div>
<div class="progress-rings">
<sl-progress-ring
class="sets"
percentage="${Math.floor(data.sets/data.activeTimer.sets*100)}"
>
<div class="progress-ring-caption">
<span>${strings.SETS}</span>
<span>${data.sets}</span>
</div>
</sl-progress-ring>
</div>
![Ba nút và một vòng tròn tiến trình.](https://web.dev/static/articles/mini-apps/mini-app-example-project/image/three-buttons-a-progress-df2f6a20c093.png?authuser=5&hl=vi)
Mô hình lập trình
Mỗi trang có một lớp Page
tương ứng giúp mã đánh dấu lit-html có thể hoạt động bằng cách cung cấp các phương thức triển khai các trình xử lý sự kiện và cung cấp dữ liệu cho từng trang.
Lớp này cũng hỗ trợ các phương thức vòng đời như onShow()
, onHide()
, onLoad()
và onUnload()
.
Các trang có quyền truy cập vào kho dữ liệu phục vụ việc chia sẻ trạng thái chung và trạng thái toàn trang cố định (không bắt buộc).
Tất cả các chuỗi đều được quản lý tập trung, do đó, tính năng quốc tế hoá được tích hợp.
Về cơ bản, việc định tuyến được trình duyệt xử lý miễn phí, vì tất cả những gì ứng dụng làm là bật/tắt chế độ hiển thị iframe và đối với các trang được tạo động, hãy thay đổi thuộc tính src
của iframe giữ chỗ.
Ví dụ bên dưới cho thấy mã để đóng một trang được tạo động.
import Page from '../page.js';
const page = new Page({
eventHandlers: {
back: (e) => {
e.preventDefault();
window.top.history.back();
},
},
});
![Trang trong ứng dụng được nhận dạng dưới dạng iframe.](https://web.dev/static/articles/mini-apps/mini-app-example-project/image/in-app-page-realized-an-25ec73e15af7f.png?authuser=5&hl=vi)
Định kiểu
Việc tạo kiểu trang diễn ra trên mỗi trang trong tệp CSS trong phạm vi riêng của trang đó.
Tức là các phần tử thường có thể được chỉ định trực tiếp qua tên phần tử, vì không thể xảy ra xung đột với các trang khác.
Các kiểu chung được thêm vào mỗi trang, vì vậy, bạn không cần phải khai báo nhiều lần các chế độ cài đặt trung tâm như font-family
hoặc box-sizing
.
Đây cũng là nơi giao diện và các tuỳ chọn chế độ tối được xác định.
Danh sách dưới đây cho thấy các quy tắc cho trang Lựa chọn ưu tiên, sắp xếp nhiều thành phần biểu mẫu trên một lưới.
main {
max-width: 600px;
}
form {
display: grid;
grid-template-columns: auto 1fr;
grid-gap: 0.5rem;
margin-block-end: 1rem;
}
label {
text-align: end;
grid-column: 1 / 2;
}
input,
select {
grid-column: 2 / 3;
}
![Trang lựa chọn ưu tiên về ứng dụng HIIT Time hiển thị một biểu mẫu ở dạng bố cục lưới.](https://web.dev/static/articles/mini-apps/mini-app-example-project/image/hiit-app-preferences-pag-3d83359174159.png?authuser=5&hl=vi)
Khoá chế độ thức của màn hình
Trong quá trình tập thể dục, màn hình không được tắt. Trên các trình duyệt hỗ trợ chế độ này, HIIT Time nhận ra điều này thông qua khoá chế độ thức trên màn hình. Đoạn mã dưới đây cho biết cách thực hiện.
if ('wakeLock' in navigator) {
const requestWakeLock = async () => {
try {
page.shared.wakeLock = await navigator.wakeLock.request('screen');
page.shared.wakeLock.addEventListener('release', () => {
// Nothing.
});
} catch (err) {
console.error(`${err.name}, ${err.message}`);
}
};
// Request a screen wake lock…
await requestWakeLock();
// …and re-request it when the page becomes visible.
document.addEventListener('visibilitychange', async () => {
if (
page.shared.wakeLock !== null &&
document.visibilityState === 'visible'
) {
await requestWakeLock();
}
});
}
Kiểm thử ứng dụng
Ứng dụng HIIT Time có sẵn trên GitHub. Bạn có thể phát bằng bản minh hoạ trong một cửa sổ mới hoặc ngay trong iframe nhúng bên dưới (mô phỏng một thiết bị di động).
Xác nhận
Bài viết này đã được Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent và Keith Gu đánh giá.