밑줄의 외부 템플릿


121

나는 밑줄 템플릿을 사용 합니다. 외부 파일을 템플릿 으로 첨부 할 수 있습니까?

Backbone View에는 다음이 있습니다.

 textTemplate: _.template( $('#practice-text-template').html() ),

 initialize: function(){                                            
  this.words = new WordList;            
  this.index = 0;
  this.render();
 },

내 HTML은 다음과 같습니다.

<script id="practice-text-template" type="text/template">
   <h3>something code</h3>
</script>

잘 작동한다. 하지만 외부 템플릿이 필요합니다 . 나는 시도한다 :

<script id="practice-text-template" type="text/template" src="templates/tmp.js">

또는

textTemplate: _.template( $('#practice-text-template').load('templates/tmp.js') ),

또는

$('#practice-text-template').load('templates/tmp.js', function(data){ this.textTemplate = _.template( data ) })

하지만 작동하지 않았습니다.

답변:


51

편집 :이 답변은 오래되고 구식입니다. 삭제하고 싶지만 "수락 된"답변입니다. 대신 내 의견을 주입하겠습니다.

나는 더 이상 이것을 옹호하지 않을 것입니다. 대신 모든 템플릿을 개별 HTML 파일로 분리했습니다. 일부는 비동기식으로로드하는 것이 좋습니다 (Require.js 또는 일종의 템플릿 캐시). 작은 프로젝트에서는 잘 작동하지만 템플릿이 많은 대규모 프로젝트에서는 페이지로드시 내가 정말 싫어하는 작은 비동기 요청을 많이하는 경우가 있습니다. (ugh ... 좋아, r.js로 초기 종속성을 미리 컴파일하여 Require.js로 해결할 수 있지만 템플릿의 경우 여전히 나에게 잘못된 느낌)

저는 grunt 작업 (grunt-contrib-jst)을 사용하여 모든 HTML 템플릿을 하나의 templates.js 파일로 컴파일하고 포함하는 것을 좋아합니다. 모든 세계의 최고 IMO ... 템플릿은 파일에 살고, 해당 템플릿의 컴파일은 런타임이 아닌 빌드 타임에 발생하며 페이지가 시작될 때 100 개의 작은 비동기 요청이 없습니다.

아래의 모든 것은 쓰레기입니다

저에게는 템플릿에 JS 파일을 포함하는 단순함을 선호합니다. 따라서 템플릿을 변수로 포함하는 view_template.js라는 파일을 만들 수 있습니다.

app.templates.view = " \
    <h3>something code</h3> \
";

그런 다음 일반 파일과 같이 스크립트 파일을 포함하고보기에서 사용하는 것처럼 간단합니다.

template: _.template(app.templates.view)

한 단계 더 나아가 실제로 coffeescript를 사용하므로 코드가 실제로 다음과 같이 보이고 줄 끝 이스케이프 문자를 피합니다.

app.templates.view = '''
    <h3>something code</h3>
'''

이 접근 방식을 사용하면 실제로 필요하지 않은 require.js가 유출되는 것을 방지 할 수 있습니다.


46
이 접근 방식은 ide에서 사용할 수있는 구문 강조, 재 형식화 및 리팩토링 기능을 잃게됩니다. 하지만 투표하지 않습니다.
Kinjal Dixit 2012 년

1
미안하지만이 답변에 반대 투표를해야했습니다. 템플릿 파일을 여전히 스크립트 파일로 유지하기 때문에 끔찍하게 투박합니다. 템플릿은 템플릿이어야하므로 Require.js를 가져 오거나 아래 koorchik의 훌륭한 솔루션을 사용해야한다면 그만한 가치가 있다고 생각합니다.
Tommi Forsström

3
@ TommiForsström 동의합니다. 저는이 접근 방식에서 멀어졌습니다. 와! 2011 년 12 월 4 일은 Backbone.js 개발의 세계에서 정말 오래 전입니다 :)
Brian Genisio

실제로이 답변을 삭제하고 싶지만 수락 된 답변이므로 삭제할 수 없습니다. 구식이며 이것보다 훨씬 더 나은 솔루션이 있습니다. 오늘은 파일을 별도의 템플릿 파일로 만들고 grunt 작업 (예 : JST)을 사용하여 별도의 templates.js 파일로 빌드하여 모두 개별적으로 가져 오는 비동기 특성을 방지합니다. IMO에 접근하는 두 세계의 최고입니다.
Brian Genisio 2014 년

템플릿이 많지 않다면 이전 솔루션이 정말 가장 효율적이라고 생각합니다.
silkAdmin 2014 년

107

다음은 간단한 해결책입니다.

var rendered_html = render('mytemplate', {});

function render(tmpl_name, tmpl_data) {
    if ( !render.tmpl_cache ) { 
        render.tmpl_cache = {};
    }

    if ( ! render.tmpl_cache[tmpl_name] ) {
        var tmpl_dir = '/static/templates';
        var tmpl_url = tmpl_dir + '/' + tmpl_name + '.html';

        var tmpl_string;
        $.ajax({
            url: tmpl_url,
            method: 'GET',
            dataType: 'html', //** Must add 
            async: false,
            success: function(data) {
                tmpl_string = data;
            }
        });

        render.tmpl_cache[tmpl_name] = _.template(tmpl_string);
    }

    return render.tmpl_cache[tmpl_name](tmpl_data);
}

여기서 "async : false"를 사용하는 것은 어떤 경우에도 템플릿이로드 될 때까지 기다려야하기 때문에 나쁜 방법이 아닙니다.

따라서 "렌더링"기능

  1. 각 템플릿을 정적 디렉토리에 별도의 html 파일로 저장할 수 있습니다.
  2. 매우 가볍다
  3. 템플릿 컴파일 및 캐시
  4. 템플릿 로딩 로직을 추상화합니다. 예를 들어 나중에 미리로드되고 미리 컴파일 된 템플릿을 사용할 수 있습니다.
  5. 사용하기 쉽다

[나는 이것이 중요하다고 생각하기 때문에 코멘트를 남기지 않고 답변을 편집하고 있습니다.]

템플릿이 네이티브 앱에 표시되지 않는 경우 "HIERARCHY_REQUEST_ERR : DOM Exception 3"-오류가 발생할 수있는 정확히 무엇입니까? "라는HIERARCHY_REQUEST_ERROR: DOM Exception 3 Dave Robinson의 답변 을 참조하십시오 ..

기본적으로 추가해야합니다.

dataType: 'html'

$ .ajax 요청에.


3
@BinaryNights-만일을 대비 dataType: 'html'하여 항상 아약스 요청에 추가해야 합니까?
Matt

중첩 된 뷰에서도 작동합니까? 보기가 다른보기를 참조하면 분명히 작동 할 수 없습니다.
T. Rossi

1
예, 중첩 된 템플릿에서도 작동합니다. <% (데이터, 'nested_template') 렌더링 = %> : 그냥 추가 도우미 렌더링과 같이 호출
koorchik

안녕하세요, "컴파일 및 캐시 템플릿"에 대해 좀 더 설명해 주시겠습니까? 렌더링 함수를 호출하려고 할 때 tmpl_data를 반환 값에 추가하지 않고 그대로 전달했습니다. 그 후 "Handlebars.compile"메서드를 호출해야했습니다. 감사합니다.
cdagli

18

이 믹스 인을 사용하면 Underscore 를 사용하여 매우 간단한 방법으로 외부 템플릿을 렌더링 할 수 있습니다 _.templateFromUrl(url, [data], [settings]). Method API는 Underscore의 _.template () 과 거의 동일 합니다. 캐싱이 포함됩니다.

_.mixin({templateFromUrl: function (url, data, settings) {
    var templateHtml = "";
    this.cache = this.cache || {};

    if (this.cache[url]) {
        templateHtml = this.cache[url];
    } else {
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            success: function(data) {
                templateHtml = data;
            }
        });

        this.cache[url] = templateHtml;
    }

    return _.template(templateHtml, data, settings);
}});

용법:

var someHtml = _.templateFromUrl("http://example.com/template.html", {"var": "value"});

2
정말 멋진 작은 믹스 인이 아주 깔끔합니다! 공유 : 환호
닉 화이트

아주 멋진 D, 이것이 제가 찾던 종류의 해결책이었습니다. 템플릿 세트를 비공개로 유지하는 데 사용할 수 있다고 생각합니다.
bigmadwolf

@abhi 대답에 제공됩니다. 또한 템플릿을로드하려면 jQuery가 필요하지만 AJAX를 통해 템플릿을로드하는 코드의 일부를 다른 라이브러리를 사용하여 취향에 맞게 다시 작성할 수 있습니다.
Dmitriy

@Dmitriy async : false는 더 이상 사용되지 않습니다. 따라서 내가 비동기 매개 변수를 사용하여 호출하면 작동하지 않습니다. 기본적으로 비동기가 true이고 syncronisilly를 호출하는 것을 의미
하므로이

@abhi, jQuery 1에서 작동합니다. * 또한 this answer stackoverflow.com/a/11755262/541961
Dmitriy

17

이 간단한 작업에 require.js를 사용하고 싶지 않았기 때문에 수정 된 koorchik 솔루션을 사용했습니다.

function require_template(templateName, cb) {
    var template = $('#template_' + templateName);
    if (template.length === 0) {
        var tmpl_dir = './templates';
        var tmpl_url = tmpl_dir + '/' + templateName + '.tmpl';
        var tmpl_string = '';

        $.ajax({
            url: tmpl_url,
            method: 'GET',
            contentType: 'text',
            complete: function (data, text) {
                tmpl_string = data.responseText;
                $('head').append('<script id="template_' + templateName + '" type="text/template">' + tmpl_string + '<\/script>');
                if (typeof cb === 'function')
                    cb('tmpl_added');
            }
        });
    } else {
        callback('tmpl_already_exists');
    }
}

require_template('a', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'a' rendering
    }
});
require_template('b', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'b' rendering
    }
});

템플릿을 자바 스크립트 객체에 저장하지 않고 문서에 추가하는 이유는 무엇입니까? 프로덕션 버전에서는 모든 템플릿이 이미 포함 된 html 파일을 생성하고 싶기 때문에 추가 ajax 요청을 할 필요가 없습니다. 그리고 동시에 코드를 리팩토링 할 필요가 없습니다.

this.template = _.template($('#template_name').html());

내 백본 뷰에서.


1
이것을 사용하면 TDD에 Jasmine을 사용하고 requirejs와 textjs 플러그인을 구현하기 전에 템플릿을 테스트하려는 scenerio에 좋습니다. 잘 했어 @Tramp
Nicholas Murray

$ .ajax에 대한 호출은 비동기식이며 결과에 따라 모든 것이 반환 된 promise의 done 메서드 내에서 실행되어야합니다.
JoshRoss

감사합니다. 나는 그것을 사용했다. 한 가지 제안 : 스크립트 태그로 추가 할 이유가 없습니다. 계속 진행하여 템플릿으로 변환하여 조회 해시에 보관할 수 있습니다. 다음은 (작동하지 않는) 바이올린 예제입니다 : jsfiddle.net/PyzeF
webnesto

async: false지금은 사용되지 않습니다
ProblemsOfSumit

이후 async: false사용되지 않습니다, 나는 추가하여 답을 향상 complete콜백을.
알렉산더

16

이것은 주제에서 약간 벗어 났을 수 있지만 Grunt (http://gruntjs.com/)를 사용할 수 있습니다. 이것은 node.js (http://nodejs.org/, 모든 주요 플랫폼에서 사용 가능)에서 실행되어 명령 줄. 템플릿 컴파일러 https://npmjs.org/package/grunt-contrib-jst 와 같은이 도구에 대한 많은 플러그인이 있습니다 . GitHub에 대한 문서, https://github.com/gruntjs/grunt-contrib-jst를 참조하십시오 . (또한 노드 패키지 관리자 https://npmjs.org/ 를 실행하는 방법을 이해해야합니다 . 매우 쉽고 다재다능하므로 걱정하지 마십시오.)

그런 다음 모든 템플릿을 별도의 html 파일에 보관하고 도구를 실행하여 모두 밑줄을 사용하여 미리 컴파일 할 수 있습니다 (JST 플러그인에 대한 종속성이라고 생각하지만 걱정하지 마십시오. 노드 패키지 관리자가 종속성을 자동으로 설치합니다).

이렇게하면 모든 템플릿이 하나의 스크립트로 컴파일됩니다.

templates.js

스크립트를로드하면 전역 (기본적으로 "JST")이 설정됩니다. 이는 함수의 배열이며 다음과 같이 액세스 할 수 있습니다.

JST['templates/listView.html']()

비슷한 것

_.template( $('#selector-to-your-script-template'))

해당 스크립트 태그의 내용을 (templates /) listView.html에 넣으면

그러나 실제 키커는 다음과 같습니다. Grunt는 'watch'라는이 작업과 함께 제공되며 기본적으로 로컬 grunt.js 파일 (기본적으로 자바 스크립트에서 Grunt 프로젝트의 구성 파일 인 파일)에 정의한 파일의 변경 사항을 모니터링합니다. ). 불만이있는 경우 다음을 입력하여이 작업을 시작합니다.

grunt watch

명령 줄에서 Grunt는 파일에 대한 모든 변경 사항을 모니터링하고 위에서 설명한 jst 작업 과 같이 변경 사항을 감지하면 grunt.js 파일에서 설정 한 모든 작업을 자동 실행합니다 . 파일을 편집 한 다음 저장하면 모든 템플릿이 여러 디렉터리 및 하위 디렉터리에 분산되어 있더라도 하나의 js 파일로 다시 컴파일됩니다.

자바 스크립트 linting, 테스트 실행, 스크립트 파일 연결 및 축소 / 추적을 위해 유사한 작업을 구성 할 수 있습니다. 그리고 모두 감시 작업에 연결될 수 있으므로 파일을 변경하면 프로젝트의 새로운 '빌드'가 자동으로 트리거됩니다.

설정하고 grunt.js 파일을 구성하는 방법을 이해하는 데 약간의 시간이 걸리지 만, 투자 한 시간을 충분히 투자 할 가치가 있으며, 사전 작업 방식으로 돌아 가지 않을 것이라고 생각합니다.


가장 좋아하는 답변입니다. 이것은 받아 들여진 대답이어야합니다. (내가 아님)
Brian Genisio 2014 년

그루터기에 좋은 진입 점. 일반 HTML에서는 잘 작동하지만 <% = price %> 또는 이와 유사한 경우 다음과 같이 표시됩니다. 예상치 못한 토큰 =, grunt에서 컴파일하지 못했습니다
mcktimo

나는 이것을하는 데 문제가 있다는 것을 제외 하고는이 접근 방식 (JST 사용)을 좋아합니다 : template: JST['test.html'](), JST에서 데이터를로드하지 않는 것 같습니다 :( 여기 내 질문 참조 : stackoverflow.com/questions/29723392/… )
timhc22

15

이것이 당신에게 도움이 될 것이라고 생각 합니다. 솔루션의 모든 것은 require.jsJavaScript 파일 및 모듈 로더 인 라이브러리를 중심으로 이루어집니다 .

위 링크의 튜토리얼은 백본 프로젝트를 구성하는 방법을 매우 잘 보여줍니다. 샘플 구현이 또한 제공된다. 도움이 되었기를 바랍니다.


3
내가 모범 사례를 구현하려고하는 프로젝트를 시작했습니다 찾고 누군가를 위해 내 사이트에 대한 참조 주셔서 감사합니다, backboneboilerplate.com
토마스 데이비스

4

나는 자바 스크립트 템플릿에 관심이 있었고 이제 백본으로 첫 걸음을 내딛고 있습니다. 이것은 내가 생각 해낸 것이고 꽤 잘 작동하는 것 같습니다.

window.App = {

    get : function(url) {
        var data = "<h1> failed to load url : " + url + "</h1>";
        $.ajax({
            async: false,
            url: url,
            success: function(response) {
                data = response;
            }
        });
        return data;
    }
}

App.ChromeView = Backbone.View.extend({
    template: _.template( App.get("tpl/chrome.html") ),
    render: function () {
        $(this.el).html(this.template());
        return this;
    },
});

App.chromeView = new App.ChromeView({ el : document.body });
App.chromeView.render();

귀하의 get함수에서 아마도 $.ajax자체를 반환하여 약속 객체를 반환하므로 템플릿이 즉시 응답하지 않는 경우를 대비하여.
Dennis Rongo 2014

4

데이터 유형을 "텍스트"로 설정해야 작동합니다.

get : function(url) {
    var data = "<h1> failed to load url : " + url + "</h1>";
    $.ajax({
        async: false,
        dataType: "text",
        url: url,
        success: function(response) {
            data = response;
        }
    });
    return data;
}

2

jQuery를 사용하여 저에게 적합한 솔루션을 찾았습니다.

jQuery.load () 메서드와 함께 밑줄 템플릿 코드를 기본 html 파일에 추가합니다.

일단 거기에 있으면 템플릿을 생성하는 데 사용합니다. 모두 동시에 발생해야합니다!

개념은 다음과 같습니다.

밑줄지도 템플릿 코드가 있습니다.

<!-- MAP TEMPLATE-->
<script type="text/template" id="game-map-template">
    <% _.each(rc, function(rowItem, index){ %>
      <ul class="map-row" data-row="<%- index %>">
        <li class="map-col <%- colItem.areaType ? 'active-area' : '' %>"></li>
        ...
</script>

이 코드를 map-template.html 이라는 파일에 넣습니다.

그 후 템플릿 파일에 대한 래퍼를 만듭니다.

<div id="templatesPool"></div>

그런 다음 해당 파일을 주 HTML 파일에 포함합니다.

머리에서 :

<!-- Template Loader -->
<script> 
    $(function(){
      $("#templatesPool").append($('<div>').load("map-template.html")); 
    });
</script> 

건배.


1

나는이 질문이 정말 오래되었다는 것을 알고 있지만 밑줄 ajax 템플릿에 대한 Google 검색의 첫 번째 결과로 나타났습니다.

나는 이것에 대한 좋은 해결책을 찾지 못하는 것에 지쳐서 내 자신을 만들었습니다.

https://github.com/ziad-saab/underscore-async-templates

AJAX를 사용하여 밑줄 템플릿을로드하는 것 외에도 <% include %> 기능을 추가합니다. 누군가에게 유용 할 수 있기를 바랍니다.


0

jQuery가 동기식으로 작동하도록하는 것이 약간 불편했기 때문에 promise를 사용하여 이전 동기식 예제를 수정했습니다. 거의 동일하지만 비동기 적으로 실행됩니다. 이 예제에서는 hbs 템플릿을 사용하고 있습니다.

var asyncRenderHbs= function(template_name, template_data) {
    if (!asyncRenderHbs.template_cache) { 
        asyncRenderHbs.template_cache= {};
    }

    var promise= undefined;

    if (!asyncRenderHbs.template_cache[template_name]) {
        promise= new Promise(function(resolve, reject) {
            var template_url= '/templates/' + template_name;
            $.ajax({
                url: template_url,
                method: 'GET',
                success: function(data) {
                    asyncRenderHbs.template_cache[template_name]= Handlebars.compile(data);
                    resolve(asyncRenderHbs.template_cache[template_name](template_data));
                },
                error: function(err, message) {
                    reject(err);
                }           
            });
        });
    } else {
        promise= Promise.resolve(asyncRenderHbs.template_cache[template_name](template_data));
    }

    return promise;
};

그런 다음 렌더링 된 html을 사용하려면 :

asyncRenderHbs('some_template.hbs', context)
    .then(function(html) {
        applicationMain.append(html);
        // Do other stuff here after html is rendered...
    })
    .catch(function(err) {
        // Handle errors
    });

참고 : 다른 사람들이 설명했듯이 모든 템플릿을 단일 templates.js 파일로 컴파일하고 웹 페이지가로드 될 때 템플릿을 가져 오기 위해 많은 작은 동기 AJAX 호출을 사용하는 것보다 처음에로드하는 것이 좋습니다.


0

전방 경고-여기 드래곤이 있습니다 :

ASP.NET 스택 (및 유사한 프레임 워크)이 js-libs의 에코 시스템과 조화롭게 작동하도록하기 위해 아래에 표시된 접근 방식을 간단히 언급합니다. 이것이 일반적인 솔루션이 아니라는 것은 말할 필요도 없습니다. 라고 한 ...

/ endforwardwarning

ASP.NET을 사용하는 경우 템플릿을 하나 이상의 부분보기 내에 배치하여 템플릿을 외부화 할 수 있습니다. .cshtml 내부 :

  @Html.Partial("path/to/template")

template.cshtml 내부 :

   // this is razorview and thusly if you ever need to use the @ character in here  
   // you will have to either escape it as @@ or use the html codepoint which is &#64
   // http://stackoverflow.com/questions/3626250/escape-character-in-razor-view-engine
   <script type="text/x-template" id="someId">
        <span class="foo"><%= name %></span>
   </script>

이제 평소처럼 템플릿을 사용할 수 있습니다.

  _.template($("#someId").html())({ name: "Foobar" });

이 이해하기 어려운 접근 방식이 누군가가 1 시간 분량의 머리를 긁는 데 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.