티스토리 뷰
Handlebars 템플릿 엔진
html코드를 더 간결하고, 리유저블하게 만들어줄 수 있는 또 다른 템플릿 엔진에는 'handlebars'가 있다.
handlebars는 기존의 html코드를 모두 변경해야하는 pug과 달리 html 코드 내의 별도의 문법이 거의 없고, if문이나 iteration같은 부분만 변경해주면 되기 때문에 ,매우 쉽다.
handlebars에서는 pug과 달리 ' products.length > 0 ' 과 같은 연산이 허용되지 않는다. handlebars 템플릿에서는 오로지 ' true or false'만 연산할 수 있기 때문에, js 파일에서 데이터를 보낼 때, 이점을 유의해주어야 한다.
// 리스폰스로 템플릿 파일을 보내는 방법은 pug와 동일하니 생략한다.
먼저 아래와 같이 handlebars를 설치해준다.
npm install --save express-handlebars@3.0
메인 소스코드에 handlebar를 import 해준다.
const expressHbs = require('express-handlebars');
엔진 설정을 해준다.
app.engine()에서 첫번째 인자는 엔진의 이름을 설정해주는 것이고 (앞으로 확장자명이 된다.) 두번째로 expressHbs()는 초기화된 뷰 엔진을 return 함으로써 엔진을 설정해준다. 이점이 pug와 다른데, pug은 express의 built in 엔진이었던 반면, handelbars는 built in 엔진이 아니기 때문에 먼저 꼭 engine 설정을 해주어야 한다. 그 이후는 pug와 같다.
app.engine('handlebars', expressHbs());
app.set('view engine', 'handlebars');
app.set('views', 'views');
그리고 이렇게 render를 하면 알아서 404.handlebars 페이지를 렌더링하고, 해당 페이지에 객체 데이터를 보낸다.
app.use((req,res,next)=>{
res.status(404).render('404',{pageTitle:"404 error"});
});
handlebars로 layout 만들기
먼저 아까 engine설정했을 때 expressHbs 함수 인자로 layout 설정을 알려주는 객체를 넘겨줘야한다.
- layoutsDir에는 layout의 위치를 쓴다. ( views/layouts/가 default이다.)
- defaultLayout에는 디폴트 레이아웃으로 할 파일의 이름을 적어준다.
- extname 에는 해당 레이아웃의 확장자명을 입력해준다. (확장자명은 engine함수의 첫번째 인자이다.)
app.engine('handlebars', expressHbs({layoutsDir: 'views/layouts/', defaultLayout: 'main-layout', extname:'handlebars'}));
main-layout 파일을 만들어주는데, 여기서 중요한 점은 if 문의 사용과 render 함수 에서 데이터를 넘겨주는 것이다.
왜냐하면 handlebars에는 pug와 달리 block이 없기 때문에 모두 if 문으로 처리를 해주어야 하기 때문이다.
또한, 앞에서 언급한것 처럼 handlebars는 true or false만 연산가능하므로, 해당 연산에 필요한 모든 데이터를 아래와 같이 js 파일의 render에서 넘겨주어야한다.
여기서 동적 데이터는 {{ }} 로 묶어주고 if문은 {{#if}} ~ {{/if}} 로 묶어주도록 한다.
또한, 헤더 아래 각각 파일별로 다른 main 소스코드를 넣을 것이므로 {{body}}라고 적어준다.
router.get('/add-product',(req,res,next)=>{
//res.sendFile(path.join(rootDir,'views','admin.html')); //파일보내기
res.render('admin',{
pageTitle:'Add Product',
activeAddProduct:true, // 현재 route가 Add-Product라고 알려준다.
productCSS:true, //link 할 CSS 파일지정을 위한 객체
formCSS:true // link 할 CSS 파일지정을 위한 객체
});
});
그리고 main layout 파일에서는 아래와같이 if문으로 해당 객체가 true인지 false인지를 연산 한 후, 그에 맞춰 html코드를 바꿀 수 있다.
- CSS link를 동적으로 변화
<title>{{ pageTitle }}</title>
<link rel="stylesheet" href="/css/main.css">
{{#if formCSS}}
<link rel="stylesheet" href="/css/form.css">
{{/if}}
{{#if productCSS}}
<link rel="stylesheet" href="/css/product.css">
{{/if}}
- active를 동적으로 변화
<li class="main-header__item"><a class="{{#if activeShop}} active {{/if}}" href="/">shop</a></li>
<li class="main-header__item"><a class="{{#if activeAddProduct}} active {{/if}}" href="/admin/add-product">add product</a></li>
그리고 해당 메인 레이아웃의 body 자리에 {{body}}를 삽입해줌으로써, 각각 handlebars마다 다른 main 내용이 들어갈 수 있게 해준다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ pageTitle }}</title>
<link rel="stylesheet" href="/css/main.css">
{{#if formCSS}}
<link rel="stylesheet" href="/css/form.css">
{{/if}}
{{#if productCSS}}
<link rel="stylesheet" href="/css/product.css">
{{/if}}
</head>
<body>
<header class="main-header">
<nav class ="main-header__nav">
<ul class="main-header__item-list">
<li class="main-header__item"><a class="{{#if activeShop}} active {{/if}}" href="/">shop</a></li>
<li class="main-header__item"><a class="{{#if activeAddProduct}} active {{/if}}" href="/admin/add-product">add product</a></li>
</ul>
</nav>
</header>
{{{ body }}}
</body>
</html>
그러면 각각의 handlebars파일에서는 <main> </main> 부분의 코드만 작성하면 된다.
'web : back-end > node js' 카테고리의 다른 글
[node js] Express: MVC 패턴 (0) | 2020.06.21 |
---|---|
[node js] Express: EJS 템플릿 엔진 (0) | 2020.06.20 |
[node js] Express: Pug 템플릿 엔진 (0) | 2020.06.18 |
[node js] Express : Request로 받은 데이터 전달하기 (0) | 2020.06.17 |
[node js] Express : 라우트의 리스폰스로 파일 보내기 (0) | 2020.06.16 |