我怎样才能在隔离的组件中使用模型,同时保持 one-way 绑定以进行模型刷新?

How can I use a model in a component in isolation but maintain a one-way bind for model refreshes?

我目前的组件根据传入的模型显示 table 个结果:

\pagedContent is a computed property of the model
{{table-test model=pagedContent}}

table 在通过查询参数选择各种过滤器时更新其内容。我一直在尝试使用以下代码对 table 标题实施一些 'sort on click' 行为:

    import Component from '@ember/component';
    import {
      computed
    } from '@ember/object';

    export default Component.extend({

      model: null,
      init() {
        this._super(...arguments);
        this.dataSorting = ['total_users']
        this.dataSortingDesc = ['total_users:desc']
      },

      sortedDataDesc: computed.sort('unsortedData', 'dataSortingDesc'),
      sortedData: computed.sort('unsortedData', 'dataSorting'),
      unsortedData: computed('model', function () {
        return this.get('model');
      }),

      actions: {
        columnsort(property) {
          if (!this.get('tableSorted')) {

            this.set('dataSortingDesc', [`${property}:desc`])
            this.set('model', this.get('sortedDataDesc'))
            this.set('tableSorted', true)

          } else {
            this.set('dataSorting', [property])
            this.set('displayModel', this.get('sortedData'))
            this.set('model', null)
          }
        },
      }
    });

排序按预期工作,但由于模型的双向绑定,我遇到了问题。模板上的其他组件也使用该模型,当对 table 中的数据进行排序时,它会为这些组件带来各种问题。

我尝试使用计算的 属性 创建一个单独的 'copy' 模型,如下所示:

  \a new property
  displayModel: computed('model', function () {
    return this.get('model');
  }),
  sortedDataDesc: computed.sort('unsortedData', 'dataSortingDesc'),
  sortedData: computed.sort('unsortedData', 'dataSorting'),
  unsortedData: computed('model', function () {
    return this.get('model');
  }),

  actions: {
    columnsort(property) {
      if (!this.get('tableSorted')) {

        this.set('dataSortingDesc', [`${property}:desc`])
        this.set('model', this.get('sortedDataDesc'))
        this.set('tableSorted', true)

      } else {
        this.set('dataSorting', [property])
        this.set('displayModel', this.get('sortedData'))
        this.set('model', null)
      }
    },

然后 table 遍历 displayModel 来创建自己。这会产生一种行为,其中列排序但随后显示 'freezes' 一旦单击列标题并且不会随着基础模型更新而更新。在这种情况下,我可以从我的其他组件中看到模型在应用新过滤器时继续更新。

我使用 oneWaydidUpdateAttrs 实现也没有成功。

如何在组件中创建 model 的副本,以便我可以在不通过 two-way 绑定更改整个模型的情况下对 table 列进行排序,同时保持一种方式绑定以便如果模型由 parent 模板更新,它也会在组件中更新?

编辑:

我创造了一个小游戏here

如果您单击 table 的 header,您可以看到两个组件都更改了它们的顺序,因为我正在处理传递的 'model'。

我想要实现的是一个工作流,在该工作流中我可以将模型传递到 table 组件以便它显示数据并且我可以对列进行排序而不影响第二个组件(也由模型)。

问题是我还需要 属性 填充 table 来刷新如果其他东西(我的 parent 模板上存在的一组过滤器)通过交互刷新模型parent 模板。

所以 'sort' 影响填充 table 的 属性,除了 属性 填充 table 之外没有别的东西对模型更新敏感parent 托管组件。

这里的问题是您在组件之间共享支持模型的数组,然后操纵该数组(Ember 知道)。如果您停止共享数组(通过将引用复制到第二个数组):

import Ember from 'ember';

export default Ember.Route.extend({
  model(){
    return [{name: "Frank", age: 22}, {name: "Alan", age: 43}, {name: "Bob", age: 56}] 
  },
  setupController(controller, model){
    controller.set('model', model);
    controller.set('tableModel', model.slice(0));
  }
});

然后改变你 application.hbs 喜欢:

{{my-component model=tableModel}}
{{second-component model=model}}

您只会看到 table 组件发生顺序变化。由于两个数组都指向相同的引用,因此您的模型本身被绑定到两个数组(即更改模型属性,如 age 会影响 modeltableModel,因为它们实际上指向相同的一块内存。但是排序只会影响 tableModel 因为你现在已经分配了两个数组

我用 my own copy 扩展了你的要点,其中我在 models 数组中操作了一个引用模型,它影响了 modelstableModels,因为数组中的底层元素是相同的引用。