Mustache Template với jQuery

Mustache.js là thư viện hỗ trợ lập trình viên giảm thiểu việc xử lý logic trong quá trình hiển thị dữ liệu lên front-end với HTML5, Javascript. Điển hình là dữ liệu có cấu trúc json. Sử dụng Mustache Template giúp code js dễ nhìn, trực quan hơn trong quá trình phát triển giao diện có nhiều thành phần tích hợp phức tạp và có tính tái sử dụng.

Để sử dụng mustache bạn tham khảo ví dụ đơn giản sau:

<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.1/mustache.min.js"></script>
  <!-- HTML template -->
<script id="template" type="x-tmpl-mustache">
  <h1>{{title}}</h1>
  <ul>
    {{#items}}
    <li>{{name}}</li>
    {{/items}}
  </ul>
</script>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
    //JSON data or from API's
    var data = {
        title: "My List",
        items: [
            {name: "Item 1"},
            {name: "Item 2"},
            {name: "Item 3"}
        ]
    };
    // Use jQuery to get the HTML template
    var template = $('#template').html();
    // Compile the template using mustache
    var html = Mustache.render(template, data);
    // Insert the HTML into the page
    $('#content').html(html);
</script>
</body>
</html>

Ví dụ trên bạn có thể thấy mã Javascript được viết tường minh, dễ mở rộng, tái sử dụng hơn so với việc cộng chuỗi html và append kết quả theo cách cũ.

Các phương thức & thuộc tính hỗ trợ

Khai báo template với mustache

Trong ví dụ trên thẻ script id=”template” chính là nơi bạn định nghĩa cấu trúc template hiển thị cho dữ liệu, sử dụng nhiều hơn 1 template bạn cần định nghĩa lại cho từng thẻ script này.

<script id="template" type="x-tmpl-mustache">
  <h1>{{title}}</h1>
  <ul>
    {{#items}}
    <li>{{name}}</li>
    {{/items}}
  </ul>
</script>

Thuộc tính type là x-tmpl-mustache hoặc text/template là bắt buộc để tránh trình duyệt thực thi mã javascript.

Khác nhau giữa type text/template và type x-tmpl-mustache

Trong HTML, thẻ script có thể được sử dụng để lưu trữ các mã nguồn JavaScript hoặc nội dung khác không hiển thị lên giao diện. Khi sử dụng mustache.js, bạn có thể chọn sử dụng 2 type khác nhau: “text/template” và “x-tmpl-mustache”. Sự khác biệt của 2 type này là:

  • text/template: là loại type mặc định của thẻ script, nó cho phép bạn lưu trữ bất kỳ nội dung nào trong thẻ script và không cần phải xử lý gì cả. Khi sử dụng mustache.js, bạn có thể sử dụng nó để lưu trữ HTML template và sử dụng mustache.js để tạo ra HTML từ template và dữ liệu JSON.
  • x-tmpl-mustache: là loại type được sử dụng riêng cho mustache.js, nó cho phép mustache.js tự động xử lý nội dung của thẻ script và tạo ra HTML từ template và dữ liệu JSON mà không cần sử dụng hàm Mustache.render.

Cả 2 type đều có thể sử dụng để lưu trữ HTML template nhưng “x-tmpl-mustache” có thể giúp cho việc sử dụng mustache.js tiện, đơn giản hơn.

Tham số dữ liệu – variable

Tất cả tham số trong mustache đều được bao bởi cặp {{variable}} và được HTML-escaped. Ở điểm này bạn lưu ý để tránh sử dụng các thư viện sử dụng cặp ngoặc tương tự dẫn tới vấn đề không tương thích, cụ thể là AngularJS.

Như bạn thấy trong ví dụ trên template HTML định nghĩa các tham số như: {{title}}, {{name}} là các thuộc tính để đánh dấu nơi chúng hiển thị. Tên tham số tương ứng với thuộc tính dữ liệu đầu vào (trong ví dụ là dữ liệu json).

Lưu ý: đối với danh sách dữ liệu là 1 mảng giá trị dạng chuỗi hoặc số bạn có thể sử dụng {{.}} trong template để hiển thị.

Do mặc định {{variable}} đều được HTML-escaped chính vì vậy nếu dữ liệu bạn có định dạng HTML trong chuỗi nội dung bạn cần loại bỏ escaped bằng cách sử dụng 1 trong 2 cú pháp sau để hiển thị dữ liệu chứa các thẻ HTML:

  • {{{variable}}}
  • {{&variable}}

Để nắm rõ hơn, bạn tham khảo ví dụ sau:

Dữ liệu JSON giả định

{
  "name": {
    "last": "Cù Kim",
    "first": "<strong>Ngọc</strong>"
  },
  "age": 35,
  "blog": "https://wikipoly.com",
  "description": "Code thuê giá tốt!"
}

Template sử dụng

<script id="template" type="x-tmpl-mustache">
  <div>
  * Họ & Tên escaped HTML: {{name.last}} {{name.first}}<br/>
  * Họ & Tên không escaped HTML: {{name.last}} {{&name.first}}<br/>
  * Tuổi: {{age}}<br/>
  * Blog: {{blog}}<br/>
  * Giới thiệu: {{description}}<br/>
  * Hiển thị variable (không bind):
  {{=<% %>=}}
  {{description}}
  <%={{ }}=%>
  </div>
</script>

Kết quả hiển thị

* Họ & Tên escaped HTML: Cù Kim <strong>Ngọc</strong>
* Họ & Tên không escaped HTML: Cù Kim Ngọc
* Tuổi: 35
* Blog: https://wikipoly.com
* Giới thiệu: Code thuê giá tốt!
* Hiển thị variable (không bind): {{description}}

Biểu thức điều kiện – sections

Trong ví dụ đầu bài bạn để ý phần hiển thị dữ liệu mình có sử dụng cặp tham số  {{&items}} … {{/items}}. Điều này có nghĩa là nếu items không có dữ liệu thì quá trình thực thi template sẽ không xảy ra. Hiểu đơn giản nó như biểu thức true/ false vậy.

Mustache quy định một tham số (kể cả list, array) có giá trị: null, undefined, false, 0, NaN hoặc chuỗi rỗng, danh sách rỗng thì dữ liệu sẽ không xử lý render hiển thị.

Template sử dụng sections

Quay lại điều chỉnh template ví dụ trên với thuộc tính {{description}} như sau:

<script id="template" type="x-tmpl-mustache">
  <div>
  * Họ & Tên escaped HTML: {{name.last}} {{name.first}}<br/>
  * Họ & Tên không escaped HTML: {{name.last}} {{&name.first}}<br/>
  * Tuổi: {{age}}<br/>
  * Blog: {{blog}}<br/>
  {{#description}}
  * Giới thiệu: {{description}}<br/>
  {{/description}}
  * Hiển thị variable (không bind):
    {{=<% %>=}}
      {{description}}
    <%={{ }}=%>
  </div>
</script>

Ở dữ liệu mẫu bạn xóa nội dung description đi., kết quả hiển thị mustache sẽ không render dòng * Giới thiệu nữa.

* Họ & Tên escaped HTML: Cù Kim <strong>Ngọc</strong>
* Họ & Tên không escaped HTML: Cù Kim Ngọc
* Tuổi: 35
* Blog: https://wikipoly.com
* Hiển thị variable (không bind): {{description}}

Hiển thị dữ liệu

Mustache.render

Để bind dữ liệu hiển thị trong mustache bạn sử dụng hàm Mustache.render với 2 tham số đầu vào là template và data. Ngoài ra để tăng tốc độ render bạn có thể sử dụng hàm Mustache.parse sau khi định nghĩa template và trước render.

Mustache.parse

Thông thường trước khi render thì mustache sẽ phân tích cú pháp từ template sau đó render. Để cache lại thao tác này cho một template ở phiên render sau thì bạn sử dụng parse. Ví dụ bạn có thể điều chỉnh lại code render như sau:

<script type="text/javascript">
    ...
    Mustache.parse(template);
    var html = Mustache.render(template, data);
    ...
</script>

Việc sử dụng Mustache.render để cache template đặc biệt hữu ích nếu quá trình hiển thị bạn loop qua danh sách dữ liệu. Khi đó hàm render ở mỗi phiên lặp sẽ không phân tích lại cú pháp template nữa qua đó tăng hiệu suất hiển thị.

Ghi chú – comment

Trong mustache để ghi chú trong template làm việc với team hoặc gợi nhớ về sau, bạn chỉ cần sử dụng dấu ! trước nội dung và đặt như sau {{! Nội dung ghi chú}}. Ví dụ:

<script id="template" type="x-tmpl-mustache">
  {{!Comment: Template ví dụ sử dụng mustache js. Nội dung ghi chú này sẽ không hiển thị khi render}}
  <div>
  * Họ & Tên escaped HTML: {{name.last}} {{name.first}}<br/>
  * Họ & Tên không escaped HTML: {{name.last}} {{&name.first}}<br/>
  * Tuổi: {{age}}<br/>
  * Blog: {{blog}}<br/>
  {{#description}}
  * Giới thiệu: {{description}}<br/>
  {{/description}}
  * Hiển thị variable (không bind):
    {{=<% %>=}}
      {{description}}
    <%={{ }}=%>
  </div>
</script>

Tổng kết

Việc sử dụng Mustache Template kết hợp với jQuery giúp code trở nên ngắn gọn, rõ ràng hơn. Đối với các dự án chưa tích hợp các thư viện hỗ trợ giao diện như AngularJS, ReactJS, VueJS, RivetsJS, Underscore.js… ngay từ đầu thì Mustache là thư viện lightweight bạn nên sử dụng để hiển thị dữ liệu dễ dàng hơn. Cá nhân mình cũng thường sử dụng mustache trong khi viết plugins, themes theo yêu cầu khách thuê code vì nó nhẹ.

Rõ ràng, việc sử dụng kết hợp 2 thư viện JavaScript này giúp code trở nên ngắn gọn và khá rõ ràng. Quan trọng là MustacheJS rất dễ học và sử dụng ngay phải không?

Để tìm hiểu chi tiết hơn về thư viện này bạn có thể tham khảo tại đây nhé: https://github.com/janl/mustache.js/