簡體   English   中英

從腳本標記中排除HTML

[英]Exclude HTML from script tag

我正在嘗試學習Handlebars.js,想到了一種在網站中使用它的方法。 這是一個單頁網站,它將有兩個容器,每個容器有三個div,它們將通過API包含嵌入式Soundcloud播放器。

當在Handlebars處理的腳本標記中包含包含API請求的div時,該站點表現得非常不可靠並且僅顯示六個玩家中的一些。 這不是真的一致,但可以一直展示不同的球員。 問題似乎是在Soundcloud javascript SDK中,但我覺得不太熟悉在那里挖掘太多。

因此我想到了一些方法來排除玩家div(見代碼),以便他們立即加載而不是作為javascript處理,但仍然顯示在藝術家的下方 - 占位符div中的標題(設置為包含結果Handlebar腳本)。

問題是我無法想出一個很好的方法,有沒有任何簡單的功能(可能有Handlebars助手),這將幫助我做我想要的?

<div id="placeholder"></div>
<script id="player-template" type="text/x-handlebars-template">
            <div id="container1">
                    Artist1 - {{title1}}
                    <div id="player1"></div>
                    Artist2 - {{title2}}
                    <div id="player2"></div>
                    Artist3 - {{title3}}
                    <div id="player3"></div>
           </div>
           <div id="container2">
                    Artist4 - {{title4}}
                    <div id="player4"></div>
                    Artist5 - {{title5}}
                    <div id="player5"></div>
                    Artist6 - {{title6}}
                    <div id="player6"></div>
            </div>
    </script>
    <script src="js/handlebars_title_script.js"></script>

一個解決方案當然是為每個Artist - Title div制作一個Handlebar模板,並將每個模板的占位符設置為僅包含Artist1 - {{title1}}的div,但這實際上破壞了使用Handlebars來最小化HTML編碼的重點。

有人給我任何提示如何解決這個問題?

編輯1:

我通過更改我的javascript找到了另一種解決方案(我最初沒有發帖,所以很明顯你無法幫助我)。

$(document).ready(function() {
    var hey = "heya";
    SC.get("/users/artist/tracks", {limit: 1}, function(tracks){
    var title_data1 = tracks[0].title;
    hey = tracks[0].title;
    alert(title_data1);
    alert(hey)
    });


//Data that will replace the handlebars expressions in our template
var playerData = {
    title1 : hey,
};

document.getElementById( 'player-placeholder' ).innerHTML = playerTemplate( playerData );

});

抱歉不好意思。 這段代碼唯一的問題是title1(在變量playerData中是Handlebars上下文)得到變量的第一個值hey(“heya”)。 當它被警告它會彈出真實的標題時,如何讓title1使用這個值而不將變量嵌入更多的javascript中(因為這是導致前面提到的錯誤,玩家出現奇怪的原因)?

注意:在整個評論中,這個答案已經發生了巨大的變化。 如果您希望看到此答案的演變,請查看早期版本。

在掌握了JsFiddle示例后,我能夠以我認為您想要的方式工作。

工作演示

HTML:

<body>
    <div id="wrapper">
        <div id="player-placeholder"><!-- rendered template goes here --></div>

        <!-- handlebars template: -->
        <script id="player-template" type="text/x-handlebars-template">
            {{#each tracks}}
                <div class="track">
                    <header class="header">
                        <span class="artist">{{user.username}}</span> - <span class="title">{{title}}</span>
                    </header>
                    <section class="player" data-uri="{{permalink_url}}">
                    </section>
                </div>
            {{/each}}
        </script>
    </div>
</body>

JavaScript的:

$(document).ready(function() {

  /*
    get your template string See:

    http://api.jquery.com/id-selector/
    http://api.jquery.com/html/
  */
  var source = $('#player-template').html();

  // compile the template into a handlebars function
  var template = Handlebars.compile(source);

  // initialize sound cloud api
  SC.initialize({
    client_id: '90fb9e15c1e26f39b63f57015ab8da0d'
  });

  /*
    This function will be called once the HTTP transaction
    started by SC.get(...) completes. Note, there's nothing
    wrong with doing this as an anonymous function, I'm
    simply assigning it to a variable to show that this
    is a distinct function that's called later
  */
  var callback = function(tracksResponse){
    /*
       once a response has been received, we'll use the response
       to generate a new context to pass to the template function.
       Note, you can use the template function in here because its
       within a closure. See:
       https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
    */
    var context = { tracks: tracksResponse };
    var html = template(context);

    /*
      assign the rendered html to your placeholder on the page
      see: http://api.jquery.com/html/
    */
    $('#player-placeholder').html(html);

    /*
      Now that the html is rendered and on the page, its time to
      setup the sound cloud players. Note the css classes I assigned
      to the track/player. This line selects all of the player's and
      runs the function over each. See:

      http://api.jquery.com/class-selector/
      http://api.jquery.com/each/
    */
    $('.track .player').each(function(index, e){
      var $this = $(this); // jQuery reference to the current object in 'each loop'

      /*
        I assigned the permalink_url of each track to an attribute called 'data-uri'
        This line gets the value of that attribute. See:

        http://api.jquery.com/data/#data2
      */
      var permalink = $this.data('uri'); 
      var urlParameters = '/&maxheight=100&maxwidth=300&format=json&sharing=false';

      /*
        finally we call the sound cloud oEmbed function feeding it the url
        stored in the element, as well as the actual element.

        (see the second argument of the each function: http://api.jquery.com/each/)
      */
      SC.oEmbed(permalink + urlParameters, e);
    });
  };

  // get tracks for your artist
  // Note the "limit" in the object controls the number of items returned
  // by sound cloud
  SC.get("/users/theshins/tracks", {limit: 5}, callback);
});

什么地方出了錯?

JavaScript是一種單線程,異步,事件驅動的語言。 那個巨大的口碑意味着JavaScript並沒有真正的線程概念(我故意無視WebWorkers)。 要解決這個限制,JavaScript中的幾乎所有IO都是非阻塞的(異步)。

每當異步IO事務開始時,它立即返回調用者並繼續執行代碼。 幾乎所有IO事務都采用“回調”或具有在IO事務完成時將調用的事件。 這意味着所有IO操作的基本模式遵循以下內容:

  • 創建一個回調函數
  • 調用IO操作,傳遞它需要完成的參數,以及回調
  • 執行立即返回
  • 將來的某個時候,會調用回調函數

在原始示例中, $(document).ready(function() { ... })一個匿名函數$(document).ready(function() { ... })隊列,以便在引發document.onReady事件時觸發。 但是,您的原始示例分配了兩個回調。 這不是問題,事實上.ready(...)旨在接受並排隊許多回調。 但是,如果你出錯了,你有兩個獨立的代碼塊,它們調用了SC.get(...)

從技術上講,如果做得對,這不會是一個問題,但你的第一個准備回調的目的是設置頁面的HTML,而你的第二個回調試圖根據頁面上的html初始化播放器控件。 請記住,這些事件和IO操作是異步的,它們將以任何順序觸發。 基本上這成了一個計時問題,你試圖初始化頁面上的控件,並生成HTML以同時顯示在頁面上。

它是如何修復的

要解決時間問題,您需要在獲取信息,構建模板HTML以及初始化控件時進行同步。 有很多方法可以做到這一點,許多框架支持promises的想法,以幫助控制異步事件被觸發的順序,並調用它們的回調。

我采用了簡單的路線並將所有SC.get調用合並為一個,然后在其回調中我渲染了把手模板並初始化了SoundCloud播放器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM