jjzjj

javascript - Ember 2,过滤关系模型(hasMany,belongsTo)并根据关系计算计算属性

coder 2024-07-26 原文

这些是我的文件:

型号

应用程序/模型/basket.js:

export default DS.Model.extend({
  name: DS.attr('string'),
  house: DS.belongsTo('house', { async: true }),
  boxes: DS.hasMany('box', { async: true })
});

应用程序/模型/box.js:
export default DS.Model.extend({
  qty: DS.attr('number'),
  basket: DS.belongsTo('basket'),
  cartLines: DS.hasMany('cart-line', { async: true })
});

应用程序/模型/cart-line.js:
export default DS.Model.extend({
  qty: DS.attr('number'),
  box: DS.belongsTo('box'),
  product: DS.belongsTo('product')
});

应用程序/模型/product.js:
export default DS.Model.extend({
  name: DS.attr('string'),
  price: DS.attr('number')
});

路线

应用程序/路线/basket.js:
export default Ember.Route.extend({
  model(params) {
    return Ember.RSVP.hash({
      basket: this.store.findRecord('basket', params.basket_id),
      boxes: this.store.findAll('box'),
      products: this.store.findAll('product')
    });
  },
  setupController(controller, models) {
    controller.setProperties(models);
    }
});

Controller

应用程序/ Controller /basket.js:
export default Ember.Controller.extend({
  subTotal: Ember.computed('boxes.@each.cartLines', function () {
    return this.products.reduce((price, product) => {
      var total = price + product.get('price');
      return total;
    }, 0);
  })
});

问题:

我是新手,所以我在学习和犯错误。对不起。

1) Ember 过滤关系的最佳方法是什么 当我第一次进入路线?
例如,现在我在我的应用程序中加载每个框 boxes: this.store.findAll('box') .我需要一种方法来不加载我的 web 应用程序中的所有框,只加载篮子中的一个。我需要直接从后端“使用过滤器查询”吗?

更新问题
2) 计算 subTotal 的最佳 Ember 方法是什么? 现在,使用下面的代码,Ember 给了我 subTotal 但只是在 console.log(tot)并在 promise 之后!为什么这个?我怎样才能等待 promise ?我不明白该怎么做:
subTotal: Ember.computed('basket.boxes.@each.cartLines', function () {
  let count = 0;
  console.log('subTotal called: ', count);
  // It should be 0 ever
  count = count + 1;

  return this.get('basket.boxes').then(boxes => {
    boxes.forEach(box => {
      box.get('cartLines').then(cartLines => {
        cartLines.reduce(function (tot, value) {
          console.log('tot:', tot + value.get('product.price'));
          return tot + value.get('product.price');
        }, 0);
      });
    });
  });
});

它给了我模板 [object Object] 因为我也在 hbs {{log subTotal}} 中使用在控制台中它给了我这个:
subTotal called:  0
ember.debug.js:10095 Class {__ember1476746185015: "ember802", __ember_meta__: Meta}
subTotal called:  0
ember.debug.js:10095 Class {__ember1476746185015: "ember934", __ember_meta__: Meta}
ember.debug.js:10095 Class {isFulfilled: true, __ember1476746185015: "ember934", __ember_meta__: Meta}
subTotal called:  0
ember.debug.js:10095 Class {__ember1476746185015: "ember1011", __ember_meta__: Meta}
ember.debug.js:10095 Class {isFulfilled: true, __ember1476746185015: "ember1011", __ember_meta__: Meta}
tot: 3.5
tot: 6
tot: 13.5
tot: 21
tot: 24.5
tot: 27
tot: 3.5
tot: 6
tot: 13.5
tot: 21
tot: 24.5
tot: 27
tot: 3.5
tot: 6
tot: 13.5
tot: 21
tot: 24.5
tot: 27

为什么显示三遍subTotal called: 0 ,无论是零个、一个还是一千个产品。他总是打三遍subTotal called: 0 , 为什么 ?

将计算属性与 promise 一起使用好吗?

3)我对这种关系封装是否正确?

更新问题 2 :

现在我正在使用这段代码,但没有成功:
import Ember from 'ember';
import DS from 'ember-data';

export default Ember.Controller.extend({

  totalCount: Ember.computed('basket.boxes.@each.cartLines', function () {
    let total = 0;
    const promise = this.get('basket.boxes').then(boxes => {
      boxes.map(box => {
      // const trypromise = boxes.map(box => {
        console.log('box:', box);
        box.get('cartLines').then(cartLines => {
          console.log('cartLines:', cartLines);
          const cartLinesPromise = cartLines.map(cartLine => {
              console.log('cartLine:', cartLine);
              // return cartLine.get('qty');
              // return cartLine;
              // });
              return {
                qty: cartLine.get('qty'),
                price: cartLine.get('product.price')
              };
              //     return cartLines.map(cartLine => {
              //       console.log('cartLine:', cartLine);
              //       return cartLine.get('qty');
              //       //   return {
              //       //     qty: cartLine.get('qty'),
              //       //     price: cartLine.get('product.price')
              //       //   };
              //     });
            })
            // });
        return Ember.RSVP
          .all(cartLinesPromise)
          .then(cartLinesPromise => {
            console.log('cartLinesPromise:', cartLinesPromise);
            // cartLinesPromise.reduce((tot, price) => {
            //   console.log('tot:', tot);
            //   console.log('price:', price);
            //   console.log('tot+price:', tot + price);
            //   return tot + price, 0;
            // });

            return total = 10;
            // return total;
          })
        });

      });

      // return total;
    });

    return DS.PromiseObject.create({ promise });
  })

})

评论是许多尝试。

在我使用的模板中:
{{log 'HBS totalCount:' totalCount}}
{{log 'HBS totalCount.content:' totalCount.content}}
Total: {{totalCount.content}}

但是promisenull内容。

我哪里错了?

任何不正确的return ?

这段代码“有希望”正确吗?

最佳答案

成为技术新手并没有什么不好,尤其是当您的问题格式正确并经过深思熟虑时。

1) 过滤关系的最佳 Ember-Data 方法是什么?

这是一个复杂的问题,有很多可能的结局。

最简单的方法就是询问该模型。

在篮子上问

给定您的模型,您可以执行以下操作:

model(params) {
  // we will return basket but make boxes ready
  return this.get('store').find('basket', params.basket_id).then(basket => {
    return basket.get('boxes').then(() => basket);
  });
}

但这几乎没有限制和优势
  • 您需要发送带有购物篮的 ID
  • 您必须启用 coalesceFindRequests让它理智
  • 它只会加载不在商店中的盒子

  • 编辑:you need to send ids with basket这意味着 basket在您的有效载荷中,必须为其盒子提供标识。如果是rest api:{basket: {id: 1, boxes: [1,2,3], ...} .然后它将检查哪些 id 尚未加载到 store 中并在此处询问 api(假设 id 为 2 的框已加载):/boxes?ids[]=1&ids[]=3 .

    问你自己
    model(params) {
      const store = this.get('store');
      const basket = params.basket_id;
    
      return RSVP.hash({
        model: store.find('basket', basket),
        boxes: store.query('box', {basket}),
      });
    },
    
  • 另一方面,只有当篮子还没有在商店中时,这种方法才会发送对篮子的请求(与以前相同)
    但始终查询框(如果您不喜欢它,则必须使用 peekAll 和过滤器来检查您是否拥有所有框或类似的 smt)。
  • 好的想法是请求将是并行的而不是串行的,因此它可能会加快速度。
  • Basket 也不必发送其盒子的 ID。
  • 您可以通过更改 query 来进行服务器端过滤。参数

  • 编辑:if you don't like it you would have to use peekAll and filter to check if you have all of them您实际上可以使用 hasMany 进行检查.

    侧载它们

    无需向服务器发送两个请求,您可以制作您的 api,以便它将框附加到有效负载中。

    只加载篮子,让休息从模板加载

    您可以仅加载最低限度(如仅加载篮子),让 ember 继续并呈现页面。它会看到你正在访问
    basket.boxes属性(property)并获取它们。这本身看起来并不好,需要一些额外的工作,如微调器等。
    但这是加快启动和初始渲染时间的一种方法。

    2) 这是计算 subTotal 的最佳 Ember 方法

    您想要计算深入异步关系的三个层次的总和,这并不容易。
    首先,我建议将 totalPrice 计算属性放入篮子模型本身。计算属性
    被懒惰地评估,因此没有性能下降,这是模型应该能够提供的。

    这是一个小片段:
    // basket.js
    const {RSVP, computed} = Ember;
    
    price: computed('boxes.@each.price', function() {
      const promise = this.get('boxes').then(boxes => {
        // Assuming box.get('price') is computed property like this
        // and returns promise because box must wait for cart lines to resolve.
        const prices = boxes.map(box => box.get('price'));
    
        return RSVP
          .all(prices)
          .then(prices => prices.reduce((carry, price) => carry + price, 0));
      });
    
      return PromiseObject.create({promise});
    }),
    

    您需要为每个级别编写类似的内容或放弃一些异步关系。
    您的计算属性的问题是 boxes.@each.cartLines不会听任何可能改变整体价格的事情(例如产品本身价格的变化)。所以它不会反射(reflect)和更新所有可能的变化。

    我会放弃一些异步关系。例如请求 /baskets/2可以侧载所有的盒子、cartLines 甚至产品。
    如果您的 api 不支持侧载,您可以通过在路由中加载所有内容来伪造它(您必须使用第二个示例 - 在 async: false 的情况下,您不能在它们进入商店之前访问盒子)。
    这将导致更简单的计算属性来计算总价格,并且在侧载的情况下还可以减少服务器和客户端糖果的压力。
    // basket.js
    const {computed} = Ember;
    
    boxes: DS.hasMany('box', {async: false}),
    
    price: computed('boxes.@each.price', function() {
      return this.get('boxes').reduce(box => box.get('price'));
    }),
    

    更新和整体后的想法

    我不认为在一个函数中做所有的总和是可行的、可行的或理智的。你最终会陷入回调 hell 或其他 hell 。此外,这不会成为性能瓶颈。

    我做了jsfiddle它基本上是上面片段的更加充实的版本。请注意,它会正确等待并传播价格,这是两个深度的 promise ,并且还应该在发生变化时更新(我也没有测试过)。

    关于javascript - Ember 2,过滤关系模型(hasMany,belongsTo)并根据关系计算计算属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40032747/

    有关javascript - Ember 2,过滤关系模型(hasMany,belongsTo)并根据关系计算计算属性的更多相关文章

    1. ruby-on-rails - 使用一系列等级计算字母等级 - 2

      这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

    2. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

      我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

    3. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

      是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

    4. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

      项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

    5. [工业相机] 分辨率、精度和公差之间的关系 - 2

      📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

    6. ruby-on-rails - 在 Controller 中干净地处理多个过滤器(参数) - 2

      我有一个名为Post的类,我需要能够适应以下场景:如果用户选择了一个类别,则只显示该类别的帖子如果用户选择了一种类型,则只显示该类型的帖子如果用户选择了一个类别和类型,则只显示该类别中该类型的帖子如果用户没有选择任何内容,则显示所有帖子我想知道我的Controller是否不可避免地会因大量条件语句而显得粗糙...这是我解决此问题的错误方法-有谁知道我如何才能做到这一点?classPostsController 最佳答案 您最好遵循“胖模型,瘦Controller”的惯例,这意味着您应该将这种逻辑放在模型本身中。Post类应该能够报告

    7. ruby - 如何计算 Liquid 中的变量 +1 - 2

      我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

    8. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

      我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

    9. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

      给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

    10. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

      我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

    随机推荐