สอนวิธีใช้ Jade Template Engine

Suranart Niamcome
SiamHTML
Published in
3 min readJan 12, 2015

บทความนี้เราจะมาลงรายละเอียดเกี่ยวกับการใช้งาน Jade ให้มากขึ้นนะครับ ไม่ว่าจะเป็นการ include และ extend ของ template การวน loop ตัวแปรเพื่อนำมาแสดงผล รวมไปถึงการใช้งาน mixins ที่จะทำให้โค้ด jade ของเรากลายเป็น snippet ที่สามารถนำไป reuse ได้ เรามาดูกันว่าฟีเจอร์ของ Jade เหล่านี้จะช่วยให้การทำงานกับ template นั้นสะดวกขึ้นมากขนาดไหน

โดยเนื้อหาของบทความนี้ก็ถือเป็นตอนที่ 3 แล้วนะครับ หากใครยังไม่ได้อ่าน 2 ตอนก่อนหน้านี้ สามารถอ่านได้ที่ด้านล่างนี้เลยครับ

Attributes

อย่างแรกเลย เรามาดูวิธีการใส่ attribute ให้กับ html tag ของเราก่อนครับ

  • class จะใช้ . เช่น .xxx
  • id จะใช้ # เช่น #xxx
  • attributes จะใช้ () เช่น (xxx="value")

สมมติ เราอยากได้ html หน้าตาแบบนี้

<ul class="nav nav-tabs" id="my-tab">
<li role="presentation" class="active"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul>

เราก็จะต้องเขียน Jade ในรูปแบบนี้ครับ

ul.nav.nav-tabs#my-tab
li(role="presentation", class="active")
a(href="#") Home
li(role="presentation")
a(href="#") Profile
li(role="presentation")
a(href="#") Messages

จะสังเกตว่าหากมีหลายๆ attribute เราก็สามารถใส่เรียงต่อๆ กันไป โดยใช้ , คั่นได้เลยครับ

Inheritance

inheritance ก็คือการที่เราสามารถสร้าง template ใหม่ที่มาจากการต่อยอด(extend) template เดิมครับ ข้อดีของการใช้ inheritance ก็คือ เมื่อใดที่เรามีการแก้ไข template แม่ พวก template ลูกๆ ที่ไป extend มาก็จะได้รับผลของการเปลี่ยนแปลงนั้นๆ ไปด้วย และที่สำคัญก็คือ template ลูกนั้น สามารถ override เนื้อหาที่มาจาก template แม่ได้ด้วย เพียงแต่เราจะต้องระบุด้วยว่าพื้นที่ส่วนไหนใน template แม่ ที่จะยอมให้ template ลูก มา override เนื้อหาได้ เพื่อจะได้เห็นภาพมากขึ้น เรามาลองทำกันเลยดีกว่าครับ

1. สร้าง template แม่ ขึ้นมา

ให้เราสร้างไฟล์ template แม่ ขึ้นมาโดยใช้ชื่อว่า base.jade แล้วใส่โค้ดด้านล่างนี้ลงไปครับ จากนั้นก็เอาไฟล์นี้ไปใส่ไว้ในโฟลเดอร์ layouts

doctype html
html(lang='th')
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
title= 'Jade Template Engine Tutorial by SiamHTML'
link(href='/css/style.css', rel="stylesheet")
body
div= 'Put content here.'
script(src='/js/jquery.js')

2. กำหนดส่วนที่จะยอมให้ template ลูก override เนื้อหาได้

ต่อมาเราจะต้องมาดูว่าส่วนไหนที่เราจะยอมให้ template ลูก มา override เนื้อหาได้ ซึ่งเราจะเรียกพื้นที่ส่วนนี้ว่า block ครับ ให้เราสร้าง block ขึ้นมาตามที่เราต้องการเลย โดย block นี้จะเป็น block เปล่าๆ หรือจะมีเนื้อหาข้างในก็ได้ หาก block ไหนมีเนื้อหาอยู่ข้างในด้วยก็หมายความว่าเนื้อหานั้นคือเนื้อหา default ของ block นั้นนั่นเองครับ

doctype html
html(lang='th')
head

block meta
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')

block title
title= 'Jade Template Engine Tutorial by SiamHTML'

block styles
link(href='/css/style.css', rel="stylesheet")

body

block content
div= 'Put content here.'

block scripts
script(src='/js/jquery.js')

จากโค้ดด้านบน จะเห็นว่าผมสร้าง block ขึ้นมาหลายจุดเลยครับ เพราะผมมองว่ามันมีโอกาสที่ template ลูกจะมีเนื้อหาแตกต่างจาก template แม่ในส่วนนั้นได้ครับ

3. สร้าง template ลูกขึ้นมา โดยกำหนดให้มันต่อยอดจาก template แม่

ทีนี้เราก็มาสร้าง template ลูก กันบ้างครับ ให้เราสร้างไฟล์ index.jade ขึ้นมา แล้วใส่โค้ดนี้ลงไปได้เลย

extends ./layouts/base

โค้ดด้านบนจะเป็นการบอกว่า template นี้ สร้างโดยการต่อยอดมาจาก base.jade นะ ซึ่งแน่นอนว่าหน้าตาของมันจะเหมือนกับ template ที่ต่อยอดมาทุกประการ

4. ใส่เนื้อหาลงใน template ลูก เพื่อ override เนื้อหาจาก template แม่

แต่บางครั้งเราก็จำเป็นต้องแก้ไขเนื้อหาบางส่วนที่เราต่อยอดมาครับ ที่เห็นชัดๆ เลยก็คือ ส่วนของ title ที่แต่ละหน้ามักจะไม่เหมือนกันนั่นเอง เวลาเราจะ override เนื้อหาของ block ส่วนไหน ก็ให้เขียนเหมือนกับตอนที่เราสร้าง block ยังไงยังงั้นเลยครับ

extends ./layouts/baseblock title
title= 'Welcome to Jade Template Engine Tutorial by SiamHTML'
block content
h1= 'Jade Template Engine Tutorial by SiamHTML'

ส่วน block ไหนที่ไม่โดน override ก็จะแสดงเนื้อหาตาม template แม่ ครับ
Includesส่วน include จะเป็นการดึงเอาเนื้อหาจาก template หนึ่งมาใส่ไว้ในอีก template หนึ่งครับ เหมาะสำหรับการแบ่ง template ออกเป็นส่วนย่อยๆ เช่น header, sidebar, footer เป็นต้น เรามาดูวิธีการใช้งานกันเลยครับ

1. แบ่ง template ออกเป็นส่วนย่อยๆ

แยก template ส่วนบนของเว็บออกมาเป็น header.jadeheader
a(href="http://www.siamhtml.com/")
img(src="/images/logo.svg")
แยก template ส่วนล่างของเว็บออกมาเป็น footer.jadefooter
p= '© 2015 SiamHTML. All rights reserved.'

2. ดึง template ย่อยมาใช้ ผ่าน Include

ทีนี้เวลาจะเรียกใช้ header หรือ footer เราก็ไม่จำเป็นต้องมาเขียนโค้ดยาวๆ ซ้ำๆ กันทุกหน้าแล้ว ให้เราไปที่ไฟล์ base.jade แล้วลองเอา include เข้ามาใช้ในส่วนของ body ดู โค้ดก็จะมีหน้าตาแบบนี้ครับbody
include ../partials/header
block contentinclude ../partials/footer

block scripts
script(src='/js/jquery.js')
จะสังเกตว่า header และ footer ของผมจะอยู่นอก block content นะครับ เพราะผมไม่อยากให้ template ลูก มายุ่งกับ design นั่นเอง
Mixinsmixin นั้นจะเป็นการเอาโค้ด Jade ที่เคยเขียนไว้แล้ว มา reuse ครับ สมมติเรามีการใช้โค้ด html ชุดนี้บ่อยๆ<div class="panel">
<h2>Header</h2>
<p>This is panel</p>
</div>
แบบนี้เราทำมันให้เป็น mixin ไปเลยดีกว่าครับ ลองดูโค้ดด้านล่างนี้mixin panel(head, content)
div.panel
h2=head
p=content
โค้ดด้านบนจะเป็นการสร้าง mixin ที่มีชื่อว่า panel ขึ้นมาครับ โดย mixin ตัวนี้จะรับ parameter 2 ตัว ก็คือ head และ content ตามลำดับ เวลาจะเรียกใช้งาน ก็ให้ใส่เครื่องหมาย + แล้วตามด้วยชื่อ mixin แบบนี้ครับ+panel('Header1', 'This is panel')
+panel('Header2', 'This is another panel')
แต่เพื่อความเป็นระเบียบเรียบร้อย ผมแนะนำให้แยกไฟล์สำหรับเก็บ mixin ออกมาต่างหากเลยจะดีกว่าครับ เวลาจะใช้กับ template ไหน ก็ให้ include เอาแบบนี้include ./mixins/panel

Iteration

มาถึงเรื่องสำคัญครับ นั่นก็คือ iteration นั่นเอง สมมติเรามีข้อมูลของบทความหลายๆ บทความ แล้วเราต้องการจะนำมันมาแสดงในหน้าเว็บ โค้ดของเราที่เขียนด้วย Express จะมีหน้าตาประมาณนี้ครับvar data = {
'articles': [
{
'title': 'Article 1',
'href': 'articles/1.html'
},
{
'title': 'Article 2',
'href': 'articles/2.html'
},
{
'title': 'Article 3',
'href': 'articles/3.html'
}
]
};
res.render('index.jade', data);
เราสามารถวน loop ค่า articles ที่ Express ส่งมาได้ง่ายๆ แบบนี้เลยครับul
each val, index in articles
li
a(href=val.href)= val.title

Conditionals

สุดท้ายมาดู conditionals ครับ สมมติเราอยากจะเช็คก่อนว่า articles นั้นมีค่ามั้ย ถ้ามีก็ค่อยให้วน loop เอาข้อมูลมาแสดง แต่ถ้าไม่ ก็ให้แสดงข้อความว่าไม่พบข้อมูลif articles
ul
each val, index in articles
li
a(href=val.href)= val.title
else
p= 'Not found.'

บทสรุป

ก็น่าจะพอเห็นภาพกันคร่าวๆ แล้วนะครับ สำหรับความสามารถของ Jade จริงๆ ที่ผมเล่ามาก็เป็นแค่ภาพกว้างๆ เท่านั้นเองนะครับ ยังมีอะไรอีกมากมายที่ผมยังไม่ได้พูดถึง เพื่อนๆ พี่ๆ น้องๆ สามารถไปศึกษาเพิ่มเติมดูได้ครับที่เว็บหลักมาถึงตรงนี้ คาดว่าหลายๆ คน คงจะพอคุ้นเคยกับ Express และ Jade กันมาพอสมควรแล้วใช่มั้ยครับ บทความต่อไปผมเลยตั้งใจจะให้เป็น workshop เกี่ยวกับการใช้ Express ร่วมกับ Jade ในการทำเว็บไซต์ รออ่านกันได้เลยนะครับ

--

--