Hướng dẫn sử dụng Page Fragment
Back to ezyarticlePage fragment trong EzyArticle là một “mảnh giao diện” có thể tái sử dụng giữa nhiều trang. Thay vì lặp lại HTML, CSS nhỏ và script nhỏ ở nhiều nơi, ta tách chúng thành các fragment rồi ghép lại khi render trang.
Page fragment là gì?
Một page fragment thường gồm 3 phần độc lập:
-
content.html: phần HTML chính hiển thị trong thân trang -
head.html: phần được chèn vào bên trong thẻ<head> -
foot.html: phần được chèn vào cuối<body>
Cách tổ chức này giúp một fragment không chỉ có giao diện, mà còn có thể mang theo phần
<meta>, <link>, <style> hoặc script cần thiết cho chính nó.
flowchart TD
A[Page Fragment] --> B[content.html]
A --> C[head.html]
A --> D[foot.html]
B --> E[Nội dung hiển thị]
C --> F[Meta, style, link, title]
D --> G[Script hoac HTML cuối trang]
Cấu trúc thư mục
Ví dụ một fragment:
page-fragments/
common/
header/
content.html
head.html
foot.html
meta.json
Trong đó:
-
commonlàpage_name -
headerlàfragment_name
Ví dụ
meta.json:
{
"title": "Common header fragment",
"contentType": "HTML",
"status": "DRAFT"
}
Nguyên lý hoạt động
Trong runtime, hệ thống nạp fragment theo cặp:
-
page_name -
fragment_name
Sau đó ánh xạ 3 file thành 3 vùng dữ liệu:
-
content.html->content -
head.html->additionalHead -
foot.html->additionalFoot
Khi view được render, các đoạn này không được in ra như text thô, mà được đưa qua template engine thêm một lần nữa. Nghĩa là nếu bên trong fragment có Thymeleaf, biểu thức đó vẫn tiếp tục được xử lý để tạo HTML cuối cùng.
sequenceDiagram
participant P as Page
participant T as Ezy block
participant F as Fragment store
participant R as Template engine
P->>T: ezy:replace hoặc ezy:utext
T->>F: Lay fragment theo page_name/fragment_name
F-->>T: content/head/foot
T->>R: Render lại nội dung fragment
R-->>P: HTML cuối cùng
Nói ngắn gọn: page fragment là “template lồng trong template”.
Hai cách dùng chính
1. Chèn trực tiếp bằng ezy:replace
Dùng khi bạn muốn gọi thẳng một fragment từ trong page hoặc từ fragment khác.
Cú pháp:
<ezy:block ezy:replace="~{page_name/fragment_name :: region_name}" />
Ví dụ:
<ezy:block ezy:replace="~{search/active :: content}" /> <ezy:block ezy:replace="~{search/active :: head}" /> <ezy:block ezy:replace="~{search/active :: foot}" />
Ý nghĩa:
-
searchlàpage_name -
activelàfragment_name -
content,head,footlà vùng cần lấy
Quy tắc quan trọng:
- chỉ chèn
:: contentvàocontent.htmlcủa page - chỉ chèn
:: headvàohead.html - chỉ chèn
:: footvàofoot.html
Ví dụ đúng với trang
home:
pages/home/content.html<ezy:block ezy:replace="~{search/active :: content}" />
pages/home/head.html<ezy:block ezy:replace="~{search/active :: head}" />
pages/home/foot.html<ezy:block ezy:replace="~{search/active :: foot}" />
2. Render từ biến pageFragments bằng ezy:utext
Dùng khi backend đã nạp sẵn fragment map cho view.
Ví dụ:
<ezy:block ezy:utext="" /> <ezy:block ezy:utext="" /> <ezy:block ezy:utext="" />
Điểm hay ở đây là giá trị lấy ra vẫn được render tiếp như Thymeleaf/HTML, nên fragment có thể chứa biến, điều kiện, lời gọi hàm backend an toàn do hệ thống cho phép.
Ví dụ hoàn chỉnh
Giả sử bạn muốn tạo fragment
post_details/content.page-fragments/post_details/content/content.html<section class="post-detail"> <h1>Chi tiet bai viet</h1> </section>
page-fragments/post_details/content/head.html<style> .post-detail { padding: 24px; } </style>
page-fragments/post_details/content/foot.html<script> console.log('post detail fragment loaded'); </script>
Sau đó nhúng vào trang:
pages/home/content.html<ezy:block ezy:replace="~{post_details/content :: content}" />
pages/home/head.html<ezy:block ezy:replace="~{post_details/content :: head}" />
pages/home/foot.html<ezy:block ezy:replace="~{post_details/content :: foot}" />
Fragment có nhận tham số không?
Có. Runtime hỗ trợ truyền tham số theo kiểu:
<ezy:block ezy:replace="~{page_name/fragment_name :: content(title='Xin chao', slug=)}" />
Các tham số này sẽ được đưa vào context render của fragment. Phần này phù hợp khi bạn muốn tái sử dụng cùng một fragment nhưng thay đổi dữ liệu đầu vào.
Lưu ý thực tế từ code:
- tham số theo dạng
name=value - hỗ trợ chuỗi
'text' - hỗ trợ expression như
Khi nào nên dùng page fragment?
Nên dùng khi:
- header, footer, banner, khối CTA được dùng lại ở nhiều trang
- một phần giao diện có cả HTML, head và foot đi kèm
- muốn tách giao diện thành các khối nhỏ để dễ bảo trì
Không nên lạm dụng khi:
- fragment quá nhỏ, chỉ 1 dòng đơn giản
- lồng fragment quá sâu làm khó debug
- đưa script lớn vào
head.html
Một số khuyến nghị thực hành tốt
- Đặt tên rõ nghĩa như
common/header,common/footer,post_details/content - Giữ
head.htmlcho meta, style, link; hạn chế logic JS nặng - Giữ
foot.htmlcho script hoặc HTML cuối trang - Cùng một fragment thì luôn ghép đúng vùng
content/head/foot - Nếu cập nhật media tĩnh, nên thêm query version như
?v=timestampđể tránh cache cũ
Quy trình sử dụng thường gặp
- Tạo thư mục fragment trong
page-fragments - Tạo
content.html,head.html,foot.html,meta.json - Đồng bộ fragment về hoặc lên server bằng extension
- Nhúng fragment vào page bằng
ezy:replacehoặc render quapageFragments - Preview
- Publish
Kết luận
Page fragment trong EzyArticle là cơ chế ghép trang theo module: mỗi fragment là một đơn vị giao diện có thể mang theo cả phần hiển thị, phần
<head> và phần cuối trang. Nhờ đó, hệ thống vừa tái sử dụng được UI, vừa giữ được khả năng render động bằng Thymeleaf.