【问题标题】:How to store values calculated in a template helper function and use them in another template function?如何存储在模板辅助函数中计算的值并在另一个模板函数中使用它们?
【发布时间】:2014-11-02 05:29:46
【问题描述】:

考虑这个假设的例子。 html:

{{#each items}}
    {{>item}}
{{/each}}
Price = {{itemTotals.totalPrice}}
Qty = {{itemTotals.totalQty}}

Js:

Template.cart.items = function () {
    var items = Items.find();
    var cartTotals = [];
    items.forEach(function(item){
        ..somecode...
        cartTotals.price += item.price;
        cartTotals.qty += 1;
    });
    return items;
}

当然,我们需要一个函数“itemTotals”。如果我们做 price = {{items.itemTotals.totalPrice}} 和数量相同,我们必须遍历项目 3 次。我尝试将总数存储为反应变量,如下所示,但无法使其工作:

Template.cart.rendered = function () {
    this.totals = new ReactiveVar([]);
}
Template.cart.items = function () {
    var items = Items.find();
    var cartTotals = [];
    items.forEach(function(item){
        ...
    });
    this.totals.set(cartTotals);
    return items;
}

Template.cart.totals = function () {
    return this.totals.get();
}

我想 1) 了解为什么没有发生反应 2) 找出是否有办法让模板函数等待另一个 - 这比从反应变量加载和重新加载值更有效

【问题讨论】:

  • 尝试在itemstotals 助手中将this.totals 替换为Template.instance().totals。还记得在items 助手中return items
  • Template.instance() 似乎没有什么不同。对于两个 get 和 set 方法,您最终会遇到“无法调用方法 get/set of undefined”错误。我很困惑为什么会这样,因为 render() 方法发生在这些调用中的任何一个之前 - 并且在方法中放置一个 console.log 证实了这一点。我应该提一下,使用 Session 变量或 deps 会导致类似的结果,所以我认为我的做法并不正确。

标签: meteor


【解决方案1】:

Walter Zalazar 建议的另一个选项也可以,但是由于 Session 的限制,使用 Session 会迫使我们将每个值(价格、数量等)存储为单独的变量。经过反复试验,我想出了以下方法将整个总计数组存储为一个反应变量:

totals = new ReactiveVar([]);

Template.cart.items = function () {
  //foreach loop as before, calculate cartTotals, etc
  totals.set(cartTotals);
  return items;
}

Template.cart.totals = function () {
  return totals.get();
}

在 html 中:

{{totals.totalPrice}}
{{totals.qty}}

【讨论】:

    【解决方案2】:

    你可以试试这样的

    你的 .html

    <template name="itemsList">
     {{#each items}}
        {{>item}}
     {{/each}}
     Price = {{totalPrice}}
     Qty = {{totalQty}}
    </template>
    

    你的 .js

    Template.itemsList.helpers({
        totalPrice: function(){
           var price= 0;
           var items= Items.find({});
           items.forEach(function(item){
               price+=item.price;
           });
           return price;
        },
        totalQty: function(){
           return Items.find({}).count();
        },
        items:function(){
          return Items.find({});
        }
    })
    

    只是工作!

    其他选项...

    Tracker.autorun(function () {
      Session.set("totalPrice");
      Session.set("totalQty");
    })
    
    Template.itemsList.helpers({
        totalPrice: function(){
          return Session.get("totalPrice");
        },
        totalQty: function(){
           return Session.get("totalQty");
        },
        items:function(){
          var price= 0;
          var items= Items.find({});
          var count= items.count();
          items.forEach(function(item){
               price+= Number(item.price);
          });
          Session.set("totalPrice",price);
          Session.set("totalQty",count);
          return items; 
        }
    });
    

    【讨论】:

    • 你能解释一下,为什么你认为它效率低下?你有一些基准吗?
    • 这可行,但在实际情况下(以上只是一个简单的示例),我们所做的远不止返回 Items.find()。想象一下我写...some code... 的附加逻辑。假设遍历项目并执行该逻辑是一项代价高昂的操作,并且总价格是作为副产品计算的。那么上面的方法效率很低,因为我们要第二次遍历项目来获取总价格,即使另一个函数已经计算了它。
    • 对不起,我删除了我之前的评论,因为你编辑了你的评论,我输入了对编辑后版本的回复。直到现在才看到你发表了另一条评论。但以上应该回答你的问题。在这种情况下,它的效率并不低,但想象一下每个 items.find 后面都有一个 for 循环,需要大量处理。
    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多