简体   繁体   English

外部JSON和外部模板 - 无法兼顾两者

[英]External JSON and External Template - Can't get both to work

I've just started getting my head around Handlebars.JS and I can see it is a very powerful tool. 我刚刚开始了解Handlebars.JS,我可以看到它是一个非常强大的工具。

I want to be able to use externally loaded templates and externally loaded JSON to keep my code clean and with less duplication across pages. 我希望能够使用外部加载的模板和外部加载的JSON来保持我的代码清洁,并减少页面重复。

At the minute I can only get one or the other working, I can load an external template with local JSON data, or load an external JSON file with a local template. 在我可以只使用其中一个工作的那一刻,我可以使用本地JSON数据加载外部模板,或者使用本地模板加载外部JSON文件。 But, I would like to do both! 但是,我想两个都做!

I can't see anything on the handlebars documentation that covers either external JSON or external templates. 我在车把文档上看不到任何内容,包括外部JSON或外部模板。

Here is the closest I've got so far... 这是我到目前为止最接近的......

My javascript... 我的javascript ...

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Please work!</title>
    <script src="//code.jquery.com/jquery-2.0.3.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.1.2/handlebars.min.js"></script>
  </head>

  <body>


    <div id="anchor">My stuff should appear here</div>

    <script>

    var jsonData;

    function user_tracker(){ 

        $.getJSON("data/JSON_test.php", function(data) {
            jsonData = JSON.stringify(data); 
        });


        $.ajax({
            url: 'data/templates/test.php', 
            cache: true,
            success: function(data) {
                source    = data;
                template  = Handlebars.compile(source);
                $('#anchor').html(template(jsonData));
            }               
        }); 


    }


    $(document).ready(function($) {
        user_tracker();
    });


    </script>
  </body>
</html>

Here is my JSON file... 这是我的JSON文件......

{ "people":
    [
        {
            "family": "Lopez",
            "name": "Hugo",
            "title": "leader",
            "place": "Paris (France)",
            "introduction": "WP:Map workshop's Dino, GIS, Gdal & D3js lightener",
            "photo": "WikiAtlas_Lopez_Hugo_Yug.png",
            "twitter": "http://www.twitter.com/Hugo_lz"
        },        
        {
            "family": "Ganesh",
            "name": "Arun",
            "title": "co-leader",
            "place": "Dharamsala (India)",
            "introduction": "GIS, D3js enthusiast, interactions designers & wikidata tinker",
            "photo": "WikiAtlas_Ganesh_Arun_Planemad.jpg",
            "twitter": "http://www.twitter.com/planemad"
        },
        {
            "family": "Lopez",
            "name": "Edouard",
            "title": "Hero",
            "place": "Bordeaux (France)",
            "introduction": "Backend admin & Frontend professional webdev, scripts & stack consulting",
            "photo": "WikiAtlas_Lopez_Edouard_Lyhana8.png",
            "twitter": "http://wwww.twitter.com/edouard_lopez"
        }
    ]
}

And here is my template file.... 这是我的模板文件....

<div>
Hey! I've loaded!
{{#people}}
            <div><img src="{{photo}}"><b><a href="{{twitter}}">{{family}} {{name}}</a></b> — {{title}}, {{place}} : {{introduction}}.</div>
{{/people}}
</div>

The template loads fine, but it appears the JSON doesn't. 模板加载正常,但看起来JSON没有。 I don't get any errors in the console at all. 我根本没有在控制台中出现任何错误。

I added the JSON.stringify because I was previously getting an error that Handlebars didn't like an object being passed to it. 我添加了JSON.stringify,因为我之前收到的错误是Handlebars不喜欢传递给它的对象。

I can't find the go-to duplicate question, but this is a very common problem in JS, and has to do with the nature of asynchronous execution. 我找不到复制问题,但这是JS中一个非常常见的问题,并且与异步执行的本质有关。

Basically, imagine you need to cook lunch; 基本上,想象你需要做午饭; and you decide to have your two kids help. 而你决定让你的两个孩子帮忙。 So you tell Joey to run to the store and get some more potatoes (because you have no potatoes left in the house), and you tell little Jen to bring you the knife from the drawer (because of course she won't cut herself, she's already four!). 所以你告诉乔伊跑到商店去买一些土豆(因为你家里没有土豆),你告诉小仁从抽屉里拿出刀子(因为她当然不会剪掉自己,她已经四岁了!) You decide you'll start chopping as soon as Jen does her errand; 你决定一旦Jen做她的差事你就会开始砍; but since Joey is not back yet, you finish chopping very, very quickly. 但由于乔伊还没有回来,你很快就完成了砍伐。 Then, your wife complains how there's no actual potatoes in the potato soup. 然后,你的妻子抱怨土豆汤中没有真正的土豆。 Joey finally comes home, having missed (a very bland) dinner. 乔伊终于回家了,错过了(非常平淡的)晚餐。 All of that could have been avoided if you waited for both kids. 如果你等两个孩子,所有这一切都可以避免。

Your jsonData is your potatoes, the errand you don't wait on. 你的jsonData是你的土豆,你jsonData的差事。 Your template is Jen's knife, the errand which you immediately follow with template compilation. 你的模板是Jen的刀,这是你随后用模板编译的差事。

There are two and a half solutions for this. 对此有两个半解决方案。

  • Not great, but easy: Send Jen for the knife only when Joey is back (or vice versa): 不是很好,但很简单:只有当乔伊回来时才送刀给Jen(反之亦然):

     $.getJSON("data/JSON_test.php", function(jsonData) { $.ajax({ url: 'data/templates/test.php', cache: true, success: function(source) { var template = Handlebars.compile(source); $('#anchor').html(template(jsonData)); } }); }); 
  • The real thing: count that all your kids are present before you start cooking: 真实的事情:在开始烹饪之前,请计算所有孩子都在场:

     var ajaxDone = 0; var jsonData, template; function runTemplate() { $('#anchor').html(template(jsonData)); } $.getJSON("data/JSON_test.php", function(data) { jsonData = data; if (++ajaxDone == 2) runTemplate(); }); $.ajax({ url: 'data/templates/test.php', cache: true, success: function(data) { var source = data; template = Handlebars.compile(source); if (++ajaxDone == 2) runTemplate(); } }); 
  • Use promises, which will do the counting for you. 使用promises,它会为你计算。

     $.when( $.getJSON("data/JSON_test.php"), $.ajax({ url: 'data/templates/test.php', cache: true, }) ).then(function(responseJSON, responseTemplate) { // ... }); 

    (I don't know off the top of my head what responseJSON and responseTemplate format ends up as, probably something like [data, statusText, jqXHR] ... so, console.log them, see for yourself where's potatoes and where's the knife.) (我不知道我的头顶是什么responseJSONresponseTemplate格式最终,可能像[data, statusText, jqXHR] ...所以, console.log他们,看看自己哪里的土豆和哪里的刀。)

EDIT: I was blindly copy-pasting, but yeah, you must not JSON.stringify here. 编辑:我是盲目的复制粘贴,但是,你不能在这里JSON.stringify Lemme quickly strip that. 勒米迅速脱掉了那个。

Due to Asynchronous nature of AJAX requests, you may end up trying to use the data before you get. 由于AJAX请求的异步性质,您可能最终会在获得之前尝试使用这些数据。 Solution is using $.Deferred like this: 解决方案是使用$.Deferred如下所示:

  <script>

var jsonData;

function user_tracker(){ 

    var jsonData = getJSONData();

    var ajaxData = getAJAXData();


    $.when(ajaxData, jsonData).done(html, json){
        var template  = Handlebars.compile(html);
        $('#anchor').html(template(json);
   }





}

 function getJSONData(){
     var defObj = $.Deferred();
     $.getJSON("data/JSON_test.php", function(data) {
       defObj.resolve(JSON.parse(data)); //parse if response in JSON 
    });
    return defObj.promise();
 }

function getAJAXData(){
  var defObj = $.Deferred();
  $.ajax({
        url: 'data/templates/test.php', 
        cache: true,
        success: function(data) {
            //source    = data;
            //template  = Handlebars.compile(source);
            //$('#anchor').html(template(jsonData));
            defObj.resolve(data);
        }               
    }); 
  return defObj.promise();
}


$(document).ready(function($) {
    user_tracker();
});


</script>

See the entire script snippet above 请参阅上面的整个脚本代码段

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM