Play JavaScript Template

+ Handlebars Basic

Created by 이항희 / javarouka.me

JavaScript로 HTML을 그릴 때

  1. 디자이너가 디자인해준 HTML을 분석한다
  2. 그 HTML을 자바스크립트 문자열로 바꾼다
  3. 문자열 중간중간에 데이터를 결합해가며
  4. document.appendChild 를 쓰거나 innerHTML을 써서 화면에 그린다
  5. 완성

이러한 구조일 것이다

var elUserInfoGridBody = document.getElementById('userInfoGridBody'), user;

// 전에 있던 영역을 지워준다
elUserInfoGridBody.innerHTML = '';

for (var i = 0, len = userList.length; i < len; i++) {

    user = userList[i];

    // 열심히 그린다
    elUserInfoGridBody.innerHTML += '<tr> <td>' + user.id + '</td> <td>' + user.name + '</td> </tr>';
}

직접 브라우저가 된 기분으로 문자열 결합을 예측하여 완성될 HTML을 예측해야 한다

DOM Api 로 처리하면?

DOM Api로 한번 해보자

var fragment = document.createDocumentFragment(),
      user;

for (var i = 0, len = userList.length; i < len; i++) {
    user = userList[i];

    var idCell = document.createElement("td");
    idCell.innerHTML = user.id;

    var nameCell = document.createElement("td");
    nameCell.innerHTML = user.name;

    var row = document.createElement("tr");
    row.appendChild(idCell);
    row.appendChild(nameCell);

    fragment.appendChild(row);
}

elUserInfoGridBody.appendChild(fragment);
function scope() ...

더 알아보기 어렵다

게다가 결국 HTML을 예측해야 하는건 매한가지.

이따위 읽을 수 있다고 한다면

Huk...

데이터가 묶이기 전에도 미리 형태를 알 수 있고

데이터에 따라 표현을 좀 더 깔끔하게 하고 싶고

마크업 작업자와의 협업도 같이 할수 있고

Handlebars

Server/Client Template

소개 몇개

  1. Mustache 계열 템플릿
  2. 사용할 수 있는 제어가 매우 한정적
  3. Template 레이아웃 기능 지원
  4. Helper 라는 기능으로 여러가지 커스터마이징 가능
  5. 유행

흐름

템플릿으로 사용할 문자열을 Handlebars.complie 함수로 컴파일

컴파일 결과에 묶을 데이터를 인자로 실행

실행 결과로 나온 문자열을 그릴 곳에 넣기

기초예제

// 데이터입니다.
var lyric = "정상에 올라 너의 이름 토한 날\n나를 누르던 앙금같은 기억도";

// 우선 핸들바로 템플릿 문자열을 컴파일합니다.
// {{식별자}} 형식으로 데이터를 표현할 수 있습니다.
// this 식별자는 묶일 데이터 바로 자기 자신을 가르킵니다.
var compiled = Handlebars.compile("<pre>{{this}}</pre>");

// 컴파일 결과로 함수가 나옵니다. 여기에 데이터를 인자로 실행시킵니다.
var html = compiled(lyric);

// 결과를 적당한 영역에 넣어줍니다.
document.getElementById("test-render-area").innerHTML = html;
RUN

템플릿 문자열을...

<script id="my-template" type="text/x-handlebars-template">
    <pre>{{this}}</pre>
</script>

이렇게 스크립트 태그에 넣어두면 HTML을 그대로 보존하면서 알아보기 쉽게 볼 수 있다

// 스크립트 태그에 붙인 아이디로 노드를 가져와서 innerHTML으로 템플릿 문자열을 얻으면~
var lyricTemplateText = document.getElementById("my-template").innerHTML;

// 그리고 컴파일
var compiled = Handlebars.compile(lyricTemplateText);

바로 간단한 테이블 그리기

먼저 사용할 데이터

var userData = [
    {
        "seq": 1,
        "id": "javarouka",
        "name": "이항희"
    },
    {
        "seq": 2,
        "id": "yellow",
        "name": "홍진호"
    },
    {
        "seq": 3,
        "id": "faker",
        "name": "이상혁"
    }
];

템플릿 작성

<script id="user-list-template" type="text/x-handlebars-template">
    {{#this}}
        <tr data-seq="{{seq}}">
            <td>{{id}}</td>
            <td>{{name}}</td>
        </tr>
    {{/this}}
</script>

다음은... 템플릿 컴파일

// 위에서 정의한 스크립트 태그 노드를 가져온다
var templateTag = document.getElementById("user-list-template");

// 그 안의 텍스트를 꺼내서 Handlebars.compile 함수로 컴파일해서 변수에 할당해둔다.
var compiled = Handlebars.compile(templateTag.innerHTML);

이제 데이터랑 묶어서, HTML을 생성한다

// 데이터를 인자로 컴파일된 템플릿 함수를 실행하면 HTML이 나온다
var html = compiled(userData);

// 나온 HTML을 원하는 영역에 그린다!
document.getElementById("user-info-grid-body").innerHTML = html;

완성

Source

Demo

간단한 날씨 뷰어 예제

화면을 그리는데 필요한 데이터는 openWeather JSONP 를 사용한다 서울날씨 데이터

JSONP 요청을 보낼 함수

var now_process = false;
var listenWeatherData = function(location) {

    if(now_process) {
        return;
    }

    now_process = true;

    var scriptTag = document.getElementById("jsonp-script");
    if(scriptTag) {
        document.body.removeChild(oldScriptTag);
    }

    scriptTag = document.createElement("script");
    scriptTag.id = "jsonp-script";
    scriptTag.type = "text/javascript";
    scriptTag.src = weatherResourceURL + location;

    document.body.appendChild(scriptTag);
}

템플릿

<script id="weather-template" type="text/x-handlebars-template">
    {{#list}}
        <h2>
            {{name}}
            <small>- {{sys.country}}</small>
        </h2>
        {{#weather}}
            <img src="http://openweathermap.org/img/w/{{icon}}.png" style="float: left; margin: 5px;">
            <h3>{{main}}</h3>
            <p>
                {{description}}
            </p>
            <div style="clear: both; height: 0;"></div>
        {{/weather}}
    {{/list}}
    </script>

동작 함수들

var renderWeather = function(weatherData) {
        content.innerHTML = weatherTemplate(weatherData);
        now_process = false;
    },

    changeLocation = function(eventObj) {
        document.title = "Weather - " + locationPicker.value;
        listenWeatherData(locationPicker.value);
    };

완성

Source

Demo

재미로 보는 템플릿들

So you need a template engine..

감사합니다

Happy Coding!