【问题标题】:Is there a way to insert between Meteor templates?有没有办法在 Meteor 模板之间插入?
【发布时间】:2015-02-13 13:08:09
【问题描述】:

我正在尝试在 Meteor 列表模板中插入广告块。代码将比我描述的更容易显示:

// dataList.js
  Template.dataList.helpers({

    dataList : function() {
      return DataList.find();
    });

// dataList.html
  <template name="dataList">
    {{#each dataList}}
      <div class="col-xs-3">
        {{name}} (and other data)
      </div>
    {{/each}}
  </template>

我想要的结果是这样的

<div class="col-xs-3">
  Jon Snow
</div>
<div class="col-xs-3">    <----This inserted programmatically 
  <div id="ad">
     Buy a Destrier - 5 Golden Stags
  </div>
</div>
<div class="col-xs-3">
  Tyrion Lannister
</div>
<div class="col-xs-3">
  The Hound
</div>

效果类似于Foodgawker.com 上的广告。我无法弄清楚如何以随机间隔以编程方式插入广告。 这是无限滚动,需要多次添加广告。

【问题讨论】:

    标签: javascript templates meteor


    【解决方案1】:

    新思路

    // client side collection, not synchronized with server side...
    DataListWithAds= new Mongo.Collection(null);
    
    Template.DataList.destroyed= function(){
      this.observer.stop();
    }
    Template.DataList.created= function(){
        // DataList is collection anywhere
        // get handler of observer to remove it later...
        this.observer = DataList.find().observe({
    
            // observe if any new document is added
            // READ : http://docs.meteor.com/#/full/observe
    
            addedAt:function(document, atIndex, before){
              console.log(atIndex, document, self);
    
              // immediately insert original document to DataListWithAds collection
              DataListWithAds.insert(document);
    
              // if some condition is true, then add ad.
              if(atIndex % 5 == 1){
                DataListWithAds.insert({
                  name:"AD", score:document.score, isAd:true
                });
              }
            }
          }) 
    }
    
    
      // use local collection to display items together with ads
    
      Template.dataList.helpers({
        dataList : function() {
          return DataListWithAds.find();
        });
      })
    

    模板也应该稍微调整一下:

    <template name="dataList">
        {{#each dataList}}
           {{#if isAd}}
               ADVERTISEMENT
          {{else}}
             <div class="col-xs-3">
                {{name}} (and other data)
              </div>
          {{/if}}
        {{/each}}
      </template>
    

    可在此处找到概念证明: http://meteorpad.com/pad/SoJe9dgp644HKQ7TE/Leaderboard

    我认为仍有一些问题需要解决,例如: - 如何使它与排序一起工作?

    老想法

    以下是一个想法,您可以如何实现您想要的结果。

    方法是客户端等到您的列表呈现(仅发生一次),然后在您选择的位置注入一个广告

    假设:

    • 您的广告在模板 adsTemplate 中定义
    • 项目在 div 中:#listContainer

    代码:

    Template.dataList.rendered = function(){
      // position after which ads should be added
      // you can generate random number
      var adsPosition = 10;
    
      // inject HTML from template **Template.adsTemplate**
      // with data **adsData** 
      // to HTML element #listContainer
      // after HTML element at position adsPosition
      Blaze.renderWithData(
        Template.adsTemplate,
        adsData,
        this.find('#listContainer'),
        this.find('#listContainer .col-xs-3:nth-child('+adsPosition+')')
      )
    }
    

    如果要注入很多广告,因为 list 应该是无限的,那么最好使用Tracker.autorun 检测新数据并相应地注入。

    【讨论】:

    • 你在野外运行过这个吗?我希望在渲染每个循环(#listContainer)中的所有文档之前渲染“dataList”模板。这会导致闪烁吗?
    • 我没有提到这是在无限卷轴上。此解决方案不会多次插入广告
    • 我最喜欢这种方法,但我仍然无法让它永久显示。它会简要显示 adsTemplate,然后在加载数据时您就看不到它了
    • @Kuba Wyrobek 它正在添加 Template.adsTemplate,但它最终位于#listContainer 的底部。它没有考虑 adsPosition
    • 我已经更新了我的答案,这似乎好多了,你不需要直接弄乱 HTML。您只需创建新的本地集合并在正确的索引处填充它。 Blaze 负责正确的渲染。祝你好运!
    【解决方案2】:

    您可以从列表中随机选择一个 _id,然后在模板中的该文档之后显示广告。

    像这样:

    //.js
    Template.dataList.created = function(){
      var ids = DataList.find().map( function( doc ){ return doc._id });
      this.showAdId = Random.choice( ids ); //need to add 'random' package of meteor core
    };
    
    Template.dataList.helpers({
      dataList: function(){
        return DataList.find({},{transform: function( doc ){
          doc.showAd = doc._id === Template.instance().showAdId;
          return doc;
        });
      }
    });
    
    //.html 
    <template name="dataList">
      {{#each dataList}}
        <div class="col-xs-3">
          {{name}} (and other data)
        </div>
        {{#if showAd}}  <!-- check new field to see whether this is the doc with an ad -->
          <div class="col-xs-3">    
            <div id="ad">
              Buy a Destrier - 5 Golden Stags
            </div>
          </div>
        {{/if}}
      {{/each}}
    </template>
    

    【讨论】:

      【解决方案3】:

      前面的答案太复杂了;只需更新您的助手:

      dataList : function() {
        var d = _.map( DataList.find().fetch(), function(v) { return {value: v}; });
        return _.union( d.slice(0,2), {
          type: 'ad',
          value: 'Buy a Destrier - 5 Golden Stags'
        } ,d.slice(2));
      });
      

      因此,dataList 会将广告插入到第三个位置。

      【讨论】:

      • 你应该提到这个解决方案的缺点(没有细粒度的更新)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-07
      • 2012-10-04
      • 1970-01-01
      • 2019-01-09
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多