- vừa được xem lúc

[EJS] Bài 6 - Viết Code Xây Dựng Giao Diện Blog (Tiếp Theo)

0 0 19

Người đăng: Semi Art

Theo Viblo Asia

Giao diện các trang đơn danh mục bài viết của thiết kế blog dạng này sẽ không có gì khác nhiều so với giao diện trang chủ, chúng ta vẫn sẽ có thanh điều hướng topnav, phần header hiển thị tên danh mục và đoạn giới thiệu ngắn, và phần main hiển thị các trích đoạn ngắn của các bài viết mới nhất thuộc danh mục đó.

Ở thời điểm mình đang soạn bài viết này thì có lẽ bạn đã hoàn thành xong code template như trên rồi. Ở đây chúng ta sẽ bắt đầu nói về nhóm template chính của blog là layout/article bao gồm:

  • Giao diện xem bài viết view.ejs
  • Giao diện soạn thảo bài viết mới add.ejs
  • Giao diện chỉnh sửa bài viết cũ edit.ejs
[view]
. |
. +-----index.ejs
. +-----[component]
. +-----[layout]
. |
. +-----[article]
. | |
. | +-----[action]
. | | |
. | | +-----view.ejs
. | | +-----add.ejs
. | | +-----edit.ejs
. | |
. | +-----index.ejs
. |
. +-----[category]
. +-----admin.ejs
. +-----home.ejs
. +-----oops.ejs

Xem lại logic hiển thị từ điểm khởi đầu

Trước khi bắt tay vào viết code template cho tệp view.ejs thì chúng ta sẽ nhìn lại một chút logic hiển thị tính từ điểm khởi đầu là tệp view/index.ejs.

<%# --- Các tham số --- layout: home | category | article | oops | admin action: view | add | edit data : Data { ... }
%> <% const makeHTML = function(layoutName) { if (layoutName == "home") return include("./layout/home", { action, data }); if (layoutName == "category") return include("./layout/category/index", { action, data }); if (layoutName == "article") return include("./layout/article/index", { action, data }); if (layoutName == "admin") return include("./layout/admin", { action, data }); if (layoutName == "oops") return include("./layout/oops", { action, data }); if ("any-other-case") return `<h1>Unsupported layout</h1>`; }; // makeHTML var HTMLcode = makeHTML(layout);
%> <%- HTMLcode %>

Khi lệnh render được phát động với tham số layout: "article", code logic ở đây sẽ gọi hàm include() trỏ tới tệp layout/article/index.ejs và thu được kết quả là code HTML để hiển thị ở dòng <%- HTMLcode %>. Hàm include() ở đây về cơ bản sẽ chạy code template trong tệp index.ejs của nhóm layout/article mà chúng ta đã viết trong bài trước:

<%# --- Các tham số --- action: view | add | edit data : Data { ... }
%> <% const makeHTML = function(actionType) { if (actionType == "view") return include("./action/view", { data }); if (actionType == "add") return include("./action/add", { data }); if (actionType == "edit") return include("./action/edit", { data }); if ("any-other-case") return `<h1>Unsupported layout</h1>`; }; // makeHTML var HTMLcode = makeHTML(action);
%> <%- HTMLcode %>

Ở đây logic hiển thị tiếp tục kiểm tra tham số action được truyền vào và chọn một trong số các tệp template chi tiết sau cùng để tạo ra code HTML trả về cho code sử dụng bên ngoài.

Bố cục trang đơn xem bài viết

Chúng ta sẽ bắt đầu với bố cục của trang đơn hiển thị nội dung bài viết cho người dùng đọc blog. Nội dung của một bài viết blog như chúng ta đã biết - là nội dung hoàn chỉnh và độc lập với các thành phần khác trong trang web và thường được đặt trong thẻ <article>. Như vậy trang đơn mà chúng ta đang xây dựng lúc này sẽ không cần component/header để hiển thị thông tin giới thiệu ngắn. Về cơ bản thì chúng ta chỉ cần sử dụng lại các component bao gồm meta.ejs, topnav.ejs, và scriptejs.

<!doctype html>
<html>
<head> <%- include("../../../component/meta.ejs", { data }) %>
</head>
<body> <%- include("../../../component/topnav.ejs" , { data }) %> <article id="article"> <div class="container"> <h1> Bài Viết Thứ 1001 </h1> <span> Thu May 05 2022 10:40:35 GMT+0700 (Indochina Time) </span> <blockquote> "There is no one who wants pain itself, who seeks after it and wants to have it, simply because they have been holding it along..." </blockquote> <h2> What is Lorem Ipsum? </h2> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum - <a href="https://www.lipsum.com/" target="_blank"> https://www.lipsum.com/ </a> </p> </div><!-- .container --> </article> <%- include("../../../component/script.ejs") %>
</body>
</html>

Ở đây bạn có thể sẽ không cần phải tạo một component riêng để tách khối <article> ra khỏi template này. Tuy nhiên mình có sử dụng một convention riêng đó là trang thông báo lỗi không tìm thấy nội dung thường được mình xem là một bài viết đặc biệt. Vì vậy nên ở đây mình sẽ tách khối <article> thành một component để tái sử dụng lại cho layout/oops.ejs.

Thêm vào đó thì chúng ta có ba bố cục của nhóm này tương ứng với các thao tác xem view, thêm mới add, và chỉnh sửa edit. Do đó nên chúng ta cũng sẽ tạo ra một nhóm component/article bao gồm các component tương ứng với các bố cục view, add, và edit.

[view]
. |
. +-----[component]
. |
. +-----[article]
. |
. +-----view.ejs
. +-----add.ejs
. +-----edit.ejs
<article id="article"> <div class="container"> <h1> Bài Viết Thứ 1001 </h1> <span> Thu May 05 2022 10:40:35 GMT+0700 (Indochina Time) </span> <blockquote> "There is no one who wants pain itself, who seeks after it and wants to have it, simply because they have been holding it along..." </blockquote> <h2> What is Lorem Ipsum? </h2> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum - <a href="https://www.lipsum.com/" target="_blank"> https://www.lipsum.com/ </a> </p> </div><!-- .container -->
</article>

Như vậy code layout mới trông sẽ gọn gàng hơn rất nhiều.

<!doctype html>
<html>
<head> <%- include("../../../component/meta.ejs", { data }) %>
</head>
<body> <%- include("../../../component/topnav.ejs" , { data }) %> <%- include("../../../component/article/view.ejs", { data }) %> <%- include("../../../component/script.ejs") %>
</body>
</html>

Bổ sung code CSS

[express-blog]
. |
. +-----[view]
. +-----[public]
. |
. +-----[css]
. |
. +-----[component]
. +-----style.css
#article { color: black; background: white; padding: 72px 0;
} #article h1 { font-size: 2.618em;
} #article h1 + span { color: lightgray; display: block; margin: 9px 0 18px;
} #article h2 { font-size: 1.618em;
} #article h3 { font-size: 1em;
} #article p { margin: 27px 0;
} #article a { color: royalblue;
} #article blockquote { background: whitesmoke; border-left: 6px solid lightgray; padding: 18px; margin: 27px 0; font-size: 21px; font-style: italic;
} #article img { display: block; max-width: 100%; height: auto; margin: 0 auto;
} #article code { background: whitesmoke; display: inline-block; padding: 3px 6px; font-family: "Noto Mono", "Consolas", "Menlo", monospace; font-size: 15px;
} #article pre { background: whitesmoke; display: block; width: 100%; margin: 36px 0; max-height: 480px; overflow-y: scroll;
} #article pre > code { display: block; padding: 72px 18px 27px; position: relative; font-family: "Noto Mono", "Consolas", "Menlo", monospace; font-size: 0.618em; line-height: 1.618; overflow-x: scroll;
} #article pre > code::before { content: "" attr(class); color: white; background: gray; display: inline-block; padding: 9px 18px; position: absolute; top: 0; left: 0;
}
@import "./component/base.css";
@import "./component/topnav.css";
@import "./component/header.css";
@import "./component/main.css";
@import "./component/article.css";

Chạy test để xem kết quả hiển thị giả định.

app.get("*", async (request, response) => { response.render("index.ejs", { layout: "article", action: "view", data : null });
}); // app.get
npm test Server started

Cung cấp tham số data

Trong thiết kế đơn giản ở đây mình chỉ sử dụng các thông tin bao gồm tiêu đề đầy đủ của bài viết title, thời điểm chỉnh sửa lần cuối edited-datetime, và nội dung của bài viết content đã được biên dịch sang code HTML từ nguồn nào đó mà khối express-blog/view không cần quan tâm tới.

Vì vậy nên chúng ta sẽ chỉ cần cung cấp duy nhất một khóa có tên là article đại diện cho bản ghi chứa nội dung của bài viết cần hiển thị; Và đồng thời định nghĩa một kiểu dữ liệu tương ứng trong view/type.

<article id="article"> <div class="container"> <h1> <%= data.get("article").get("title") %> </h1> <span> <%= data.get("article").get("edited-datetime") %> </span> <%- data.get("article").get("content") %> </div><!-- .container -->
</article>
const Article = class extends Map { constructor() { super(); this.set("title", "Tiêu đề bài viết") .set("content", "Nội dung đầy đủ của bài viết...") .set("edited-datetime", new Date().toString()); return this; }
}; // Article module.exports = Article;

Viết lại test để hiển thị các thông tin mặc định của class Article mới.

app.get("*", async (request, response) => { var Article = require("./view/type/Article"); var data = require("./data") .set("article", new Article()); response.render("index.ejs", { layout: "article", action: "view", data });
}); // app.get
npm test Server started

Như vậy là chúng ta đã thực hiện xong những thiết lập cơ bản cho nhóm layout/article và viết xong template đơn giản cho trang hiển thị nội dung bài viết với bố cục action/view.ejs. Trong những bài viết tiếp theo, chúng ta sẽ hoàn thành hai bố cục còn lại của nhóm layout/article trước khi quay lại Sub-Series ExpressJS để viết code điều hành cho nhóm article.

(Sắp đăng tải) [EJS] Bài 7 - Viết Code Xây Dựng Giao Diện Blog (Tiếp Theo)

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 525

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 433

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 153

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 145

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 110

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 245