Web/Frontend

handlebar를 활용한 템플릿 작업

WakaraNai 2021. 7. 6. 01:11
728x90
반응형

handlebar

대표적인 template 라이브러리

 

구글에 handlebar cdn을 검색하여 스크립트 태그 복사해오기

min은 mini file로 압축된 파일을 의미

min이 마지막에 붙은 것으로 복사해오기

https://cdnjs.com/libraries/handlebars.js

 

handlebars.js - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers

Handlebars provides the power necessary to let you build semantic templates effectively with no frustration - Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving

cdnjs.com

<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js" 
integrity="sha512-RNLkV3d+aLtfcpEyFG8jRbnWHxUqVZozacROI4J2F1sTaDqo1dPQYs01OMi1t1w9Y2FdbSCDSQ2ZVdAC8bzgAg==" 
crossorigin="anonymous" 
referrerpolicy="no-referrer">
</script>

 

 

 

html에 다음과 같이 template 코드를 생성

<script type="myTemplate" id="listTemplate">
	<li>
     <div>게시자 : {{name}}</div>
     <div class="content">{{content}}</div>
     <div>좋아요 갯수 <span> {{like}} </span></div>
     <div class="comment">
       <div>{{comment}}</div>
     </div>
  </li>
</script>

 

 

js에서 replace로 치환하는 방법 대신,

handlebar 라이브러리로 사용해서 결과를 얻을 수 있다

<script>
	var template = document.querySelector("#listTemplate").innerText;
	var bindTemplate = Handlebars.compile(template);  //bindTemplate은 메서드입니다.
</script>

 

compile은 함수를 반환하는 함수

데이터가 들어오면 바로 작업할 수 있도록

미리 만들어진 template 문자열을 가져와서 이 함수가 변수로 잠시 기억해 둠

 

정확히는, pre-compile이라고 말함

template 작업 시 이 용어를 많이 사용

 

이제 bindTemplate 변수를 이용하여 template 작업을 할 수 있음

 

 

전체 코드

<!DOCTYPE html>
<html lang="en">

<head>

</head>

<body>

  <h1> template using handlebar </h1>

  <section class="show"></section>

  <script type="myTemplate" id="listTemplate">
      <li>
         <div>게시자 : {{name}}</div>
         <div class="content">{{content}}</div>
         <div>좋아요 갯수 <span> {{like}} </span></div>
         <div class="comment">
           <div>{{comment}}</div>
         </div>
      </li>
    </script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"
    integrity="sha512-RNLkV3d+aLtfcpEyFG8jRbnWHxUqVZozacROI4J2F1sTaDqo1dPQYs01OMi1t1w9Y2FdbSCDSQ2ZVdAC8bzgAg=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script>
    var data = {
      "id": 88,
      "name": "crong",
      "content": "새로운 글을 올렸어요",
      "like": 5,
      "comment": "댓글이다"
    };

    var template = document.querySelector("#listTemplate").innerText;
    // pre-compile
    var bindTemplate = Handlebars.compile(template);  //bindTemplate은 메서드입니다.
    console.log(bindTemplate);

    var resultHTML = bindTemplate(data);
    console.log(resultHTML);

    var show = document.querySelector(".show");
    show.innerHTML = resultHTML;
  </script>

</body>

</html>

 

 

 

 

배열이 포함된 경우

예를 들어 comment가 1개 이상일 때

var data = {
  	"id" : 88,
    "name" : "crong",
    "content" : "새로운글을 올렸어요",
    "like" : 5, 
    "comment" : ["댓글이다", "멋진글이네요", "잘봤습니다"]
};

 

 

반복문을 넣어서 처리

each 부분을 자세히보자

handlebar 라이브러리의 문법. #을 붙여서 헬퍼 기능임을 명시.

/each를 만날 때 까지 반복이 일어남

 

이 문법을 이용해 <div class="comment">를 다음과 같이 수정

<script type="myTemplate" id="listTemplate">
    <li>
        <div>게시자 : {{name}}</div>
        <div class="content">{{content}}</div>
        <div>좋아요 갯수 <span> {{like}} </span></div>
        <div class="comment">
        <h3>댓글목록</h3>
        {{#each comment}}
            <div>{{@index}}번째 댓글 : {{this}}</div>
        {{/each}}
        </div>
    </li>
</script>

 

 

 

 

data 자체가 많아진 경우

var data = [
	{"id" : 88, "name" : "crong", "content" : "새로운글을 올렸어요", "like" : 5, "comment" : ["댓글이다", "잘했어요"]},
	{"id" : 28, "name" : "hary", "content" : "전 오늘도 노래를 불렀어요", "like" : 0, "comment" : ["제발고만..","듣고싶네요 그노래"]},
	{"id" : 23, "name" : "pororo", "content" : "크롱이 항상 말썽을 피워서 행복해~", "like" : 4, "comment" : []},
	{"id" : 5, "name" : "pobi", "content" : "물고기를 한마리도 잡지 못하다니..", "like" : 5, "comment" : ["댓글이다", "멋진글이네요", "잘봤습니다"]}
];

 

!! 핵심은 bindTemplate()을 루프를 돌면서 여러 번 실행하고 차곡차곡 합친다는 점

 

1. forEach 사용

var innerHtml = "";

data.forEach(function (item, index) {
	innerHtml += bindTemplate(item);
});

 

 

2. reduce를 사용

var innerHtml = data.reduce(function(prve, next) {
	return prve + bindTemplate(next);
}, "");

 

 

전체 코드

style 추가

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    li {
      list-style: none;
      padding: 10px;
      border-top: 2px solid gray;
    }
  </style>

</head>

<body>

  <h1> template using handlebar </h1>

  <section class="show"></section>

  <script type="myTemplate" id="listTemplate">
      <li>
         <div>게시자 : {{name}}</div>
         <div class="content">{{content}}</div>
         <div>좋아요 갯수 <span> {{like}} </span></div>
         <div class="comment">
           <h3>댓글목록</h3>
           {{#each comment}}
              <div>{{@index}}번째 댓글: {{this}}</div>
           {{/each}}
         </div>
      </li>
    </script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"
    integrity="sha512-RNLkV3d+aLtfcpEyFG8jRbnWHxUqVZozacROI4J2F1sTaDqo1dPQYs01OMi1t1w9Y2FdbSCDSQ2ZVdAC8bzgAg=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script>
    var data = [
      { "id": 88, "name": "crong", "content": "새로운글을 올렸어요", "like": 5, "comment": ["댓글이다", "잘했어요"] },
      { "id": 28, "name": "hary", "content": "전 오늘도 노래를 불렀어요", "like": 0, "comment": ["제발고만..", "듣고싶네요 그노래"] },
      { "id": 23, "name": "pororo", "content": "크롱이 항상 말썽을 피워서 행복해~", "like": 4, "comment": [] },
      { "id": 5, "name": "pobi", "content": "물고기를 한마리도 잡지 못하다니..", "like": 5, "comment": ["댓글이다", "멋진글이네요", "잘봤습니다"] }
    ];

    var template = document.querySelector("#listTemplate").innerText;
    var bindTemplate = Handlebars.compile(template);

    //loop를 돌면서 bindTemplate을 실행
    var resultHTML = data.reduce((prev, next) => {
      return prev + bindTemplate(next);
      //next가 다음 번째의 prev가 된다
    }, "");

    var show = document.querySelector(".show");
    show.innerHTML = resultHTML;
  </script>

</body>

</html>

 

 

 

조건 상황에 따른 처리

예로 댓글이 없는 경우에는 다른 메세지로 처리해야 한다면?

 

template은 말 그대로 고정되어 있지만 handlebar에서 if를 사용하여 처리 가능

<script type="myTemplate" id="listTemplate">
    <li>
        <div>게시자 : {{name}}</div>
        <div class="content">{{content}}</div>
        <div>좋아요 갯수 <span> {{like}} </span></div>
        <div class="comment">
        <h3>댓글목록</h3>
        {{#if comment}}
            {{#each comment}}
                <div>{{@index}}번째 댓글 : {{this}}</div>
            {{/each}}
        {{else}}
            <div>댓글이 아직 없군요</div>
        {{/if}}
        </div>
    </li>
</script>

 

 

 

 

 

참고

help function 사용

좋아요 개수가 5개 이상이면 "축하해요. 좋아요가 5개 이상입니다"라믄 문자열을 추가해보겠습니다

 

likes 라는 커스텀 항목을 추가했습니다.

<script type="myTemplate" id="listTemplate">
    <li>
        <div>게시자 : {{name}}</div>
        <div class="content">{{content}}</div>

        {{#likes like}}
            {{like}}
        {{/likes}}

        <div class="comment">
        <h3>댓글목록</h3>
        {{#if comment}}
            {{#each comment}}
                <div>{{@index}}번째 댓글 : {{this}}</div>
            {{/each}}
        {{else}}
            <div>댓글이 아직 없군요</div>
        {{/if}}
        </div>
    </li>
</script>

 

 

이제 다양한 조건을 설정하는 likes helper를 만들겁니다.

registerHelper를 이용하여 likes와 관련된 것들을 실행하게 해줍니다.

 

#likes를 만나면 "likes"로 등록된 함수를 찾아서 실행

    Handlebars.registerHelper("likes", function (like) {
      if (like > 4) {
        return "<span>축하해요 좋아요가 " + like + "개 이상입니다!</span>";
      } else if (like < 1) {
        return "아직 아무도 좋아하지 않아요..";
      } else {
        return like + "개의 좋아요가 있네요";
      }
    });

 

전체 코드

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    li {
      list-style: none;
      padding: 10px;
      border-top: 2px solid gray;
    }
  </style>

</head>

<body>

  <h1> template using handlebar </h1>

  <section class="show"></section>

  <script type="myTemplate" id="listTemplate">
    <li>
        <div>게시자 : {{name}}</div>
        <div class="content">{{content}}</div>

        {{#likes like}}
            {{like}}
        {{/likes}}

        <div class="comment">
        <h3>댓글목록</h3>
        {{#if comment}}
            {{#each comment}}
                <div>{{@index}}번째 댓글 : {{this}}</div>
            {{/each}}
        {{else}}
            <div>댓글이 아직 없군요</div>
        {{/if}}
        </div>
    </li>
</script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"
    integrity="sha512-RNLkV3d+aLtfcpEyFG8jRbnWHxUqVZozacROI4J2F1sTaDqo1dPQYs01OMi1t1w9Y2FdbSCDSQ2ZVdAC8bzgAg=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script>
    var data = [
      { "id": 88, "name": "crong", "content": "새로운글을 올렸어요", "like": 5, "comment": ["댓글이다", "잘했어요"] },
      { "id": 28, "name": "hary", "content": "전 오늘도 노래를 불렀어요", "like": 0, "comment": ["제발고만..", "듣고싶네요 그노래"] },
      { "id": 23, "name": "pororo", "content": "크롱이 항상 말썽을 피워서 행복해~", "like": 4, "comment": [] },
      { "id": 5, "name": "pobi", "content": "물고기를 한마리도 잡지 못하다니..", "like": 5, "comment": ["댓글이다", "멋진글이네요", "잘봤습니다"] }
    ];

    Handlebars.registerHelper("likes", function (like) {
      if (like > 4) {
        return "<span>축하해요 좋아요가 " + like + "개 이상입니다!</span>";
      } else if (like < 1) {
        return "아직 아무도 좋아하지 않아요..";
      } else {
        return like + "개의 좋아요가 있네요";
      }
    });

    var template = document.querySelector("#listTemplate").innerText;
    var bindTemplate = Handlebars.compile(template);

    //loop를 돌면서 bindTemplate을 실행
    var resultHTML = data.reduce((prev, next) => {
      return prev + bindTemplate(next);
      //next가 다음 번째의 prev가 된다
    }, "");

    var show = document.querySelector(".show");
    show.innerHTML = resultHTML;
  </script>

</body>

</html>

 

 

728x90
반응형

'Web > Frontend' 카테고리의 다른 글

생성자 패턴으로 TabUI 만들기  (0) 2021.07.07
Clean Code  (0) 2021.07.06
jQuery 프레임워크에 대해  (0) 2021.07.01
[JS] 객체리터럴, this, bind()  (0) 2021.07.01
[JS] 배열 메소드  (0) 2021.07.01