Mức độ khó: 3
Yêu cầu: xem qua phần 1 để hiểu lý do của việc ứng dụng template.
Xét lại đạon mã HTML sau:
Ta phân tích các điểm khác nhau giữa các trang:
- Nội dung thẻ <title>
- Nội dung thẻ <h1 id="title">
- Nội dung thẻ <div id="detail">
Ta tạm dùng 3 câu trúc dữ liệu để quản lý 3 trang của chúng ta, cụ thễ như sau:
type Info struct {
string Title
string Detail
}
Cấu trúc này dành cho 2 trang About và Contact. Một cách hơi lười biếng ta dùng luôn cấu trúc này đẻ quản lý từng sản phẩm (một sản phẩm cũng gồm 1 tên và 1 mô tả).
Không thể dùng cấu trúc Info để quản lý trang chủ được, ta phải tạo riêng cho nó 1 struct:
type Home struct {
string Title
[]Info Products
}
Chúng ta có Products là 1 mảng (nói chính xác hơn là 1 slice) các Info. Hai cấu trúc có điểm chung và điểm khác biệt, điều này khiến ta không có cách đơn giản nào để dùng chung 1 template cho cả trang Home và các trang Contact, About.
Có 2 lựa chọn, một là thay đổi cấu trúc dữ liệu, 2 là thay đổi cấu trúc template. Giải pháp 1 thật sự không khả thi, trong thực tế cấu trúc dữ liệu của chúng ta sẽ bị ràng buộc không dễ gì tùy biến (dữ liệu có thể được lưu trong một hệ CSDL). Và việc thay đổi câu trúc template cũng thường xuyên xảy ra hơn.
Chúng ta tạo 3 file: tmpl.html, detail_home.html và info_home.html, đặt 3 file này ngang hàng với app.yaml, hãy xem xét một cách kỹ lưởng cả 3:
tmpl.html (hãy ghi nhớ sự thay đổi ở các dòng: 4, 45, 56)
detail_home.html (bảng danh sách sản phẩm của trang home được tách ra tại đây, lưu ý dòng 13)
detail_info.html
Còn đây là code đầy đủ:
Tới đây việc giải thích chương trình phải chia thành 2 khâu: thiết kế và lập trình:
Khâu thiết kế:
Chắ hẳn bãn phải phát hiện ký hiệu {{.Title}} (dòng 4, file tmpl.html) ký hiệu này tương đương việc ta truy xuất tới trường dữ liệu Title của object mà ta truyền vào template. Template tmpl.html ở trường hợp này là giao diện chính, nó sẽ load thêm giao diện "detail" phụ tại dòng 56. Chúng ta có 2 giao diện detail, một cho trường dữ liệu Info.Detail, một cho trường dữ liệu Home.Products. Tùy thuộc vào người dùng muốn xem trang nào, ta sẽ load template phụ và gắn nó với template chính.
Ghi chú: {{template "detail" .}} dấu "." phía sau tên template phụ hiểu như tham số, ta một lần nữa truyền toàn bộ object cho template detail.
Khâu lập trình:
- Dòng 10 - 18: Chúng ta bắt đầu với việc khai báo 2 cấu trúc Info và Home.
- Dòng 20: đọc nội dung file tmpl.html, tạo 1 template (chưa hoàn chỉnh). Lưu ý biến template là 1 biến toàn cục để tránh quá trình tạo template cứ phải lập đi lập lại mỗi khi người dùng chuyển trang.
- Dòng 27 - 34: chuẩn bị dữ liệu - trong thực tế đây có thể là đoạn mã lấy dữ liệu từ CSDL.
- Từ dòng 36 trở đi là đoạn code quản lý việc chiết xuất giao diện tùy theo trang được yêu cầu:
- Ta phải Clone (tạo 1 bản sao) template chính trước khi sửa cho từng trường hợp, nên nhớ template là biến mặc định.
- Dòng 42 và 53: tùy theo trang người dùng muốn xem, ta sẽ xử lý tiếp file detail_home.html hay deatil_info.html. Và gọi hàm Execute, lúc này 1 trong 2 file trên sẽ đc gộp lại với file tmpl.html tạo nên giao diện hoàn chỉnh. Hàm Execute cũng đảm nhiệm việc phản hồi mã HTML cho người dùng.
Người lập trình chỉ cần trao đổi với người thiết kế việc "trường hợp nào, phần nào". Người thiết kế chỉ cần biết cấu trúc dữ liệu cho từng trường hợp cụ thể.
Kỹ thuật này sẽ đem lại khả năng thuận tiện trong quá trình phát triễn (tất nhiên các bạn cần nắm vững nguyên tắc làm việc) thế nhưng lại hao tốn thêm một số tài nguyên. Nhìn chung sự hao tốn này chỉ thật sự ảnh hưởng tới những trang web có lưu lượng cực lớn.
TODO:
Đọc thêm: http://golang.org/pkg/text/template/ và http://golang.org/pkg/html/template/ . Tối ưu hóa code chương trình trong bài này nếu bạn có thể.
Không có nhận xét nào:
Đăng nhận xét