Hôm nay mình và các bạn sẽ cùng làm quen với một Template Engine sử dụng cùng với NodeJS rất hiệu quả và phổ biến nhé.
Trong mô hình MVC, các bạn biết rằng, phần View để có thể hiển thị dữ liệu động cho cùng một form nào đó, thì chúng ta cần phải có các template dựng sẵn.
Đối với lập trình web application trên NodeJS, chúng ta có thể sử dụng một số Template Engine sau:
- EJS : Là một JavaScript Template library vô cùng dễ sử dụng, cú pháp đơn giản, rõ ràng.
- Mustache: Là một Logic-less templates cũng khá nổi tiếng với những ai hay code java script để bind dữ liệu từ chuỗi JSON. Template này sử dụng trên rất nhiều ngôn ngữ, phiên bản sử dụng cho NodeJS các bạn có thể tìm ở đây: https://github.com/raycmorgan/Mu
- jQuery Templates plugin: Một template là plugin của jquery cũng vô cùng dễ dùng và khá quen thuộc với các bạn từng làm nhiều về js client để bind dữ liệu từ các đối tượng dạng json ra html.
Để khỏi bỡ ngỡ với quá nhiều cái mới trong Express, chúng ta sẽ cùng nhau đi từ những phần nhỏ của nó. Hôm nay chúng ta sẽ bắt đầu từ Jade.
Tản mạn như vậy là hơi nhiều và dài dòng. Chúng ta bắt tay vào làm thôi nào.
Như bài trước, chúng ta làm quen với một ứng dụng web đầu tiên là trang web với nội dung là lời chào Hello World.
var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/html"}); response.write("Hello World"); response.end(); }).listen(8080);Các bạn chú ý, ở phần này mình đã thay đổi:
"Content-Type": "text/plain"Thành
"Content-Type": "text/html"Vì để có thể out ra được html với các thẻ định dạng như p, div, span...cùng với css trong đó.
Để nhận biết được điều này, các bạn đơn giản thử hai đoạn code sau sẽ rõ:
var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/plan"}); response.write("<h1>Hello World</h1><p>Chào các bạn, mình đến từ YourNodeJS.com</p>"); response.end(); }).listen(8080);và
var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/html"}); response.write("<h1>Hello World</h1><p>Chào các bạn, mình đến từ YourNodeJS.com</p>"); response.end(); }).listen(8080);Ok, bây giờ bài toán đặt ra là: Bạn cần hiển thị một cái gì đó chẳng hạn như trang chủ của blog như hình đơn giản sau đây, và dữ liệu tùy biến được. Có nav panel, có header của blog, có Cột content ở giữa là danh sách các post ngắn gọn có thumb, có một đoạn lead ngắn gọn, có các tags của bài đó, có cột bên trái là các box Đọc nhiều nhất, danh sách tags của toàn blog, rồi box liên kết website chẳng hạn. Bạn có thể tùy biến cái thổ tả gì bạn muốn, tùy theo yêu cầu, nhu cầu, sở thích hoặc sở đếch thích gì của bạn cũng được. Phía dưới có hẳn phần paging luôn. Thích bạn có thể làm cái banner chèn vào phần Top để nhìn cho nó hoành tráng.
Yên tâm, hôm nay, với việc sử dụng jade, cùng với kiến thức bạn đã có từ bài Đọc ghi dữ liệu từ XML thì việc xuất ra một trang blog như thế này chỉ là trong tầm tay, và chỉ mất chưa đầy 1 tiếng. He He.
Để làm bài toán này, chúng ta sẽ chia làm các bước sau:
- Chuẩn bị dự án: bao gồm tạo cây thư mục, file dữ liệu, js, css, image cần thiết.
- Thiết kế html của blog, tạo template.
- Lấy dữ liệu, bind vào html và hiển thị ra client.
Jade như đã nói là một template engine giống bạn viết view trong MVC, để từ đó bạn bạn bind dữ liệu vào đó và xuất thành html.
Như tại trang chủ của Jade có nói rõ:
Jade is a clean, whitespace sensitive syntax for writing html.Nghĩa là đối với Jade, mọi cú pháp viết html đã tinh giản hết, không còn phải đóng mở các thẻ (tag), không phải thêm các từ khóa cơ bản như: class, div, id..., các tag bọc lồng nhau đơn giản là dùng các khoảng trắng để thể hiện (thường người ta dùng tab cho dễ nhìn), đó là bạn thụt lề các tag này vào, ra là được. Để dễ hình dung, chúng ta nhìn vào ví dụ sau:
doctype html html(lang="en") head title= pageTitle script(type='text/javascript'). if (foo) bar(1 + 5) body h1 Jade - node template engine #container.col if youAreUsingJade p You are amazing else p Get on it! p. Jade is a terse and simple templating language with a strong focus on performance and powerful features.Chuyển thành HTML sẽ như sau:
<!DOCTYPE html> <html lang="en"> <head> <title>Jade</title> <script type="text/javascript"> if (foo) bar(1 + 5) </script> </head> <body> <h1>Jade - node template engine</h1> <div id="container" class="col"> <p>You are amazing</p> <p>Jade is a terse and simple templating language with a strong focus on performance and powerful features.</p> </div> </body> </html>Jade rất dễ sử dụng từ viết tag, chèn text, javascript, link, add thuộc tính, rồi đặt id, class đặc biệt thú vị đó là cho sử dụng vòng lặp, hằng biến, điều kiện cũng như dữ liệu từ bên ngoài.
Chúng ta sẽ đi từ những ví dụ đơn giản, đến nâng cao nhé.
Tạo một thư mục
JadeEx
, sau đó cài đặt module của jade bằng lệnh:
$node install jadeTạo hai file sau:
- template.jade: Là file jade mà chúng ta sẽ code jade vào đó
- index.js: Là file mà chúng ta sẽ build ra html từ template là xuất ra trình duyệt.
var jade = require('jade'); var html = jade.renderFile('template.jade'); var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/html;charset=utf-8"}); response.write(html); response.end(); }).listen(8080);Hiện tại file template chúng ta đang rỗng, nên chả in ra cái gì cả.
Giờ bạn thử đoạn code sau vào file template nhé.
doctype html html(lang='en') head title Jade body h1 Jade - node template engineKết quả xuất ra html sẽ là:
<!DOCTYPE html> <html lang="en"> <head> <title>Jade</title> </head> <body> <h1>Jade - node template engine</h1> </body> </html>Chúng ta sẽ có các cách viết cho phần tag, class, text, id, javascript...lần lượt như sau:
Tạo tag đơn giản
div address i strongoutput sẽ là:
<div> <address></address><i></i><strong></strong> </div>
Đưa text vào nội dung tag:
h1 Welcome to Jade p | Text can be included in a number of | different ways. p. This way is shortest if you need big blocks of text spanning multiple lines.Out put là:
<h1>Welcome to Jade</h1> <p> Text can be included in a number of different ways. </p> <p> This way is shortest if you need big blocks of text spanning multiple lines. </p>
Chèn id, class và thuộc tính vào tag
h1#title Welcome to Jade button.btn(data-action="bea") AwesomeOut put sẽ là:
<h1 id="title">Welcome to Jade</h1> <button data-action="bea" class="btn">Awesome</button>Thật là đơn giản phải không các bạn.
Bây giờ là đến phần chèn dữ liệu động, và vòng lặp.
Đến đây dữ liệu chúng ta put từ bên ngoài vào nên không render file thông thường nữa, mà chúng ta cần compile nó. Vậy nên cần thay đổi lại file index.js một chút.
var jade = require('jade'); var fs = require('fs'); var popularPosts = {posts : [{id: 1, title:"NodeJS là gì?" },{ id: 2, title:"Viết ứng dụng Hello World bằng NodeJS" },{ id: 3, title:"Sử dụng Jade trong NodeJS như thế nào?" }]}; var jadetemplate = jade.compile(fs.readFileSync('template.jade', 'utf8')); console.log(popularPosts.length); var html = jadetemplate(popularPosts); console.log(html);Chúng ta có list các Bài viết Đọc nhiều, gồm 3 bài với id, tiêu đề. Giờ chúng ta cần xuất ra html list như sau:
- NodeJS là gì?
- Viết ứng dụng Hello World bằng NodeJS
- Sử dụng Jade trong NodeJS như thế nào?
Ở file template.jade ta sử lại như sau:
ul - each post in posts li.item #{post.title}Mình giải thích tý xíu cả hai đoạn code trên.
Ở đoạn code của index.js, để bind dữ liệu ngoài vào, ta cần dử dụng đến chức năng compile của jade. Là compile chuỗi jade string vào một function, sau đó chúng ta sẽ render ra html với data truyền vào. Cú pháp:
// Compile a function
var fn = jade.compile('string of jade', options);
// Render the function
var html = fn(locals);
Ở ví dụ trên, string of jade chúng ta đọc từ file template ra thông qua hàm readFileSync của file system, options thì bao gồm name, doc type, cache... phần này ta sẽ tìm hiểu sau. Ở ví dụ trên ta không dùng đến.Kế đến là phần render với data. locals là một đối tượng chính là phần data ta truyền vào, trong trường hợp này là list post. Thường ta phải truyền vào là: locals.posts = popularPosts.Post. Nhưng ở đây ta chỉ truyền vào một dữ liệu, nên không cần thiết. Đối với nhiều dữ liệu, chẳng hạn truyền cả posts, cả categories, cả comments chẳng hạn. Thì ta sẽ gán vào locals. Ở phần này ta sẽ có ví dụ ở bài tiếp theo.
Ở template, ta chú ý:
Dùng dấu
-
để bắt đầu một đoạn code giống javascript. Ở đây duyệt hết các post trong list post, với mỗi post
, thì gán post.title
vào thẻ li
. Ok, hiểu sơ lược vậy đã. Giờ ta chạy thử xem sao nào:
$npm index.js
Nếu output ra là:
<ul> <li class="item">NodeJS là gì?</li> <li class="item">Viết ứng dụng Hello World bằng NodeJS</li> <li class="item">Sử dụng Jade trong NodeJS như thế nào?</li> </ul>Là bạn đã thành công rồi đó.
Bây giờ chúng ta sẽ phát triển lên một tý.
Trường hợp bạn cần lồng các list con vào nữa thì sao? Ví dụ như list cây danh mục chẳng hạn.
- Ngôn ngữ lập trình
- .NET
- PHP
- Java
- Hệ cơ sở dữ liệu
- MS SQL
- MySQL
- Oracle
- Hệ điều hành
- Windows
- MAC OSX
- Linux
Hoàn toàn đơn giản, cú pháp template cũng như trên mà thôi.
ul.cate - each category in categories li.item #{category.name} ul.subcate - each subcate in category.listsubcates li.subitem #{subcate.name}Ở index.js ta truyền dữ liệu vào, và thay đổi một chút để xuất ra hml xem trên trình duyệt xem thế nào nhé.
var jade = require('jade'); var fs = require('fs'); var listCategory = { categories : [ { id: 1, name : "Ngôn ngữ lập trình", listsubcates : [ { id : 11, name : ".NET" }, { id : 12, name : "PHP" }, { id : 13, name : "Java" } ] }, { id: 2, name : "Hệ cơ sở dữ liệu", listsubcates : [ { id : 21, name : "MS SQL Server" }, { id : 22, name : "MySQL" }, { id : 23, name : "Oracle" } ] }, { id: 3, name : "Hệ điều hành", listsubcates : [ { id : 21, name : "Windows" }, { id : 32, name : "MAC OSX" }, { id : 33, name : "Linux" } ] } ] }; var jadetemplate = jade.compile(fs.readFileSync('template.jade', 'utf8')); var html = jadetemplate(listCategory); var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/html;charset=utf-8"}); response.write(html); response.end(); }).listen(8080);Ok, chạy lệnh:
$node index.jsMở trình duyệt lên và kiểm tra:
http://localhost:8080/
Kết quả như hình sau là bạn thành công rồi nha:
Giờ chúng ta thêm chút style cho nó nhé.
Thay đổi nội dung file template thành:
doctype html html(lang='vn') head meta(charset='utf-8') title Danh sách chuyên mục link(href='http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet') style(type='text/css'). ul.cate{border: 1px solid #ACACAC;width: 200px;margin: auto;} li.item{font-weight: 700;font-size: 15px;} ul.subcate{font-style: italic;color: blue;} body ul.cate - each category in categories li.item #{category.name} ul.subcate - each subcate in category.listsubcates li.subitem #{subcate.name} script(src='http://code.jquery.com/jquery.js')Chú ý có 3 thứ mới nhé:
1. Chèn link file css bên ngoài. Mình sử dụng:
link(href='http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet')2. Chèn link js bên ngoài:
script(src='http://code.jquery.com/jquery.js')3. Chèn style inner html:
style(type='text/css'). ul.cate{border: 1px solid #ACACAC;width: 200px;margin: auto;} li.item{font-weight: 700;font-size: 15px;} ul.subcate{font-style: italic;color: blue;}Ở 1,2 mình đưa vào để các bạn nắm được cách chèn thôi, chứ trong ví dụ ta cũng không dùng. Ở ví dụ là chèn đoạn style cho các ul, li của ta thêm chút xíu cho nó thay đổi thôi.
Giờ chạy lại xem kết quả thế nào nào.
Oh, thay đổi style rồi nhé.
html Output:
<!DOCTYPE html> <html lang="vn"> <head> <meta charset="utf-8"> <title>Danh sách chuyên mục</title> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> ul.cate { border: 1px solid #ACACAC; width: 200px; margin: auto; } li.item { font-weight: 700; font-size: 15px; } ul.subcate { font-style: italic; color: blue; } </style> </head> <body> <ul class="cate"> <li class="item">Ngôn ngữ lập trình <ul class="subcate"> <li class="subitem">.NET</li> <li class="subitem">PHP</li> <li class="subitem">Java</li> </ul> </li> <li class="item">Hệ cơ sở dữ liệu <ul class="subcate"> <li class="subitem">MS SQL Server</li> <li class="subitem">MySQL</li> <li class="subitem">Oracle</li> </ul> </li> <li class="item">Hệ điều hành <ul class="subcate"> <li class="subitem">Windows</li> <li class="subitem">MAC OSX</li> <li class="subitem">Linux</li> </ul> </li> <script src="http://code.jquery.com/jquery.js"></script> </ul> </body> </html>Một số điểm lưu ý:
- Để thụt đầu dòng trong template các bạn có thể dùng space hoặc tab, tuy nhiên cần phải dùng đồng nhất và đều. Việc thụt không đúng sẽ dễ gây ra lỗi, cũng như các thẻ không lồng đúng vào nhau.
- Ở dữ liệu JSON, các bạn chú ý phải đúng tên thuộc tính, đúng mảng hoặc list khi truyền sang file template.
Ở bài tiếp theo, chúng ta sẽ nâng cao lên với việc tạo một trang home của một blog đơn giản, như muc tiêu đề ra ban đầu nhé. Và dữ liệu là ta load từ file xml vào.
Có bất cứ lỗi hay vấn đề gì cần trao đổi. Các bạn để lại comment nhé.
0 comments