Viết HTML bằng EJS để tránh lặp lại

Bạn sẽ làm gì khi code HTML mà gặp những thành phần lặp đi lặp lại và chỉ khác một chút như danh sách tin tức. Copy paste? Khi cần sửa thì sẽ sửa từng cái một? Hmm. Sử dụng framework như React, Vue để tạo component? Đôi khi hơi quá nâng cao so với nhu cầu hiện tại? Đây là lúc bạn có thể tìm đến các template engines. Một vài Javascript template engines tiêu biểu là Pug (trước đây tên là Jade), Handlebars, EJS, Mustache. Chúng hỗ trợ việc viết HTML nhanh hơn, gọn hơn và dễ sửa đổi, bảo trì hơn.

Cách hoạt động chung của những Javascript template engines này là render những đoạn code trông giống như HTML pha trộn với code Javascript

Cá nhân mình thích sử dụng EJS nhất vì giữ nguyên HTML tags và chỉ mở ngoặc để chèn thêm Javascript khi cần. Còn Pug sử dụng cú pháp rút gọn, xóa bỏ HTML tags. Đúng ra thì viết như Pug dễ nhìn hơn và nhanh hơn, nhưng mình lại muốn viết HTML bình thường như EJS để tiện lấy nguyên cả file template gồm cả HTML cả vòng lặp để nhúng vào các framework khác sau này khi cần. Hơn nữa, EJS còn cho tùy biến cú pháp viết HTML của nó để nhái theo các ngôn ngữ khác tùy ý bạn khiến việc đưa EJS vào các framework bên ngoài càng dễ hơn.

Ví dụ về cách sử dụng EJS. Ở đây mục tiêu của mình sẽ là tạo danh sách tin tức gồm 3 tin tức, mỗi tin lại có ảnh thumbnail và tiêu đề.

Các bước làm

Bước 1. Chuẩn bị dữ liệu

Bước 2. Viết HTML theo cú pháp của template engines đó

Bước 2. Viết hàm Javascript rồi chạy ở Nodejs để render HTML vừa viết thành HTML bình thường

Đầu tiên

Mình sẽ cài đặt package ejs

npm install ejs

Bước 1. Chuẩn bị dữ liệu

Ở bước này các bạn nên viết dữ liệu ra một file riêng ví dụ tên là data.json, không nên khai báo dữ liệu ở cùng chỗ với template vì sẽ không tiện tìm lại, sửa, hoặc tái chế lại project. Lát nữa mình sẽ import cả object này để sử dụng

{
    "posts": [
        {
            "img": "<https://i.ibb.co/R6LwjhX/Large-group-of-business-people-in-convention-centre-3-D-generated-image.jpg>",
            "title": "Nâng cao văn hóa kinh doanh trong nền kinh tế thị trường ở Việt Nam hiện nay"
        },
        {
            "img": "<https://i.ibb.co/WtWC4nm/Silhouette-of-construction-worker-with-crane-and-cloudy-sky-for-preparation-of-welcome-2022-new-year.jpg>",
            "title": "Lợi nhuận công ty chứng khoán: Bùng nổ và phân hoá sâu sắc"
        },
        {
            "img": "<https://i.ibb.co/6DRKqzf/Modern-gadgets-in-interior-of-coworking-office-during-COVID-19-epidemic-Chairs-and-desk-for-support.jpg>",
            "title": "Giải pháp bảo tồn và sử dụng bền vững vốn tự nhiên ở Việt Nam"
        }
    ]
}

Bước 2. Viết HTML theo cú pháp của template engines đó

Tạo một file ejs để chứa HTML trước khi render, đặt tên ví dụ là template.ejs

Bạn viết HTML bình thường, khi cần viết vòng lặp bạn hãy dùng thẻ đóng mở đoạn Javascript là <% để viết code Javascript. Trong vòng lặp thì khi đóng thẻ kết thúc đoạn Javascript, HTML sẽ được in ra mà không cần thêm lệnh in hay cú pháp gì. Nhưng trong đoạn HTML muốn in ra một biến Javascript bạn phải dùng thẻ mở Javascript<% kèm gạch ngang <%-

        <div>
        <%
         for (let post of posts){
        %>

            <img src="<%- post.img %>">
            <h3> <%- post.title %> </h3>
        <%
                             }
                %>
    </div>

Biến posts chính là một property của object data ban nãy, có thể sử dụng được luôn không cần thông qua gọi lại biến data

Khi cần comment phải comment dấu # bên trong thẻ Javascript: <%#

<%#  for (item of %> 

Nếu comment ở ngoài

<!-- <%  for (item of %> -->

thì đoạn code Javascript lỗi vẫn được compile trước, rồi sau đó mới comment out ở HTML đã compiled, nên nếu code Javascript đang viết dở dang hoặc lỗi thì sẽ bị báo lỗi bình thường

Bước 3. Viết hàm render rồi chạy ở Nodejs để render HTML vừa viết thành HTML bình thường

Tạo 1 file javascript ví dụ index.js

Ở đây mình sẽ import object dữ liệu đã chuẩn bị trước ban nãy và đặt tên biến là data

const data = require('./data.json');

Tiếp đến dùng lệnh renderFile của object ejs. Với các tham số

  • Đường dẫn file template chứa hTML
  • File dữ liệu
  • Options
  • Hàm callback sau khi nhận được đoạn HTML đã được render

Phần options mình để null nhưng các bạn có thể tham khảo ở document của EJS để xem các options. Một options mình rất thích là delimiter, để nhái theo các ngôn ngữ khác để khi viết template được thuận tay hơn và dễ nhúng vào các framework khác.

VD: Khi muốn nhái PHP nào đó cho tiện mình sẽ set up openDelimiter là < closeDelimiter là > và delimiter là ?

Phần hàm callback mình sẽ hứng error để throw và hứng đoạn HTML đã render để viết vào 1 file HTML bình thường tên index.html Mình sẽ dùng filesystem của Nodejs để thực hiện điều đó.

const ejs = require("ejs");
const fs = require('fs');

ejs.renderFile('template.ejs', data, null, function (err, str) {
     if (err)  throw err;

    fs.writeFile("index.html", str, function(err) {
         if (err)  throw err;

});
  }

);

Chạy file index.js

node index

Nếu muốn tự động render lại mỗi khi có sự thay đổi ở các file template

Mình sẽ dùng package nodemon để watch file index.js và chạy lại nó khi có bất kì file ejs, js, json nào trong project hiện tại có sự thay đổi

nodemon index.js -e js, ejs, json

Toán bộ code ở đây https://github.com/moevl/ejs

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Mòe

10 bài viết.
387 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
136 45
Google cách học tốt Tiếng Anh thì ra hàng đống kết quả nhưng bạn mãi không dùng được cái nào. Vậy thay vì tìm cách học tốt hãy đọc thử những cách h...
Mòe viết hơn 3 năm trước
136 45
White
44 10
(Ảnh) Dùng CSS để "sửa" nội dung HTML Ngoài nguyên nhân là muốn chơi nổi thì lí do phải dùng code CSS để tác động vào HTML là khi bạn không được...
Mòe viết 3 năm trước
44 10
White
36 16
Các khái niệm riêng của Wordpress dễ gây nhầm lẫn Ai muốn làm theme động luôn và không muốn hiểu lý thuyết có thể bỏ qua phần này. Ngay ở documen...
Mòe viết gần 3 năm trước
36 16
Bài viết liên quan
White
16 1
Lấy fake path của file trong html input Ngữ cảnh: em cần làm một cái nút tải ảnh lên có preview. GIải pháp đầu: Dùng (Link) đọc file ảnh thành ba...
Hà Phạm viết hơn 5 năm trước
16 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
10 bài viết.
387 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!