【问题标题】:aurelia property observation for an object that is bound from the parent从父对象绑定的对象的 aurelia 属性观察
【发布时间】:2017-12-08 12:30:33
【问题描述】:

我有一个关于 aurelia 的问题。假设我有一个产品类,这个产品有标签。一个具体的例子:一件衬衫是一种产品,它有一些用户可以查询的标签,比如 Men、XL、blue 等。它们的 JSON 表示就像

{
  "id": 3,
  "name": "Shirt",
  "sku": "WCZR-1",
  "tags": [
    {
      "id": 1,
      "name": "XL"
    },
    {
      "id": 2,
      "name": "Blue"
    }
  ]
}

如果管理员正在查看该产品的详细视图并且可以编辑标签,他将查看如下视图:

<div class="form-group">
                <label>SKU</label>
                <input type="text" value.bind="item.sku">
</div>
<div class="form-group">
    <label>Tags</label>
        <tag-manager item.bind="item"></tag-manager>
</div>

请注意,我还有另一个名为 &lt;tag-manager&gt; 的自定义元素,它是产品详细信息元素的子元素。您可能已经猜到了,它在其导出中公开了一个可绑定对象:@bindable item = null;

这样,父元素将产品传递给子元素,管理员可以使用此标签管理器在其中添加\删除标签。为了让管理员能够编辑标签,他需要单击编辑按钮。 这会将项目置于编辑模式。父元素(产品详细信息元素)通过在用户单击编辑按钮时向产品添加InEditMode 属性来实现这一点。

enterEditMode(){
    this.item.inEditMode = true;
    this.savedItem = JSON.parse(JSON.stringify( this.item ));
}

注意inEditMode属性不是来自web api,是动态添加的。

现在,这主要是有效的,当产品处于编辑模式时,子元素(标签管理器)可以从产品中添加\删除标签,并且父子元素都可以看到产品标签集合被修改。来自标签管理器的示例代码:

removeTag(tag){
    this.item.tags = this.item.tags.filter(function(el){
        return el.id !==tag.id;
    })
}

addTag(tag){
    this.item.tags.push(tag);
}

这些功能可以正常工作并成功修改项目的标签集合,其中一个不工作的是 product.InEditMode 属性。当父元素(详细视图将产品置于编辑模式时,标签管理器仅在视图激活时识别这一点。但在初始加载后单击父元素上的编辑|取消并更改父元素中的 inEditMode 属性不会反映之后在子视图中。所以虽然产品的标签属性正在被观察,但inEditMode属性并没有被孩子观察。如果我在aurelia中导入观察者定位器并观察属性,它没有任何区别。示例代码:

import {ObserverLocator} from 'aurelia-framework';

    var subscription = this.observerLocator
      .getObserver(this.product, 'inEditMode')
      .subscribe(this.onChange);
  }
      onChange(newValue, oldValue) {
      //this method is called only once at the activation of the child,
      //no clicks in the parent can trigger this method again
      }

正如在 cmets 中看到的,onChange 方法在激活时只被调用一次;激活后,对父元素的无点击(编辑、取消编辑)将反映在子元素中,不会再次调用onChange。

我可以通过使用eventAggregator 来完成这项工作,但我真的很想知道为什么我不能从父对象观察到对象的布尔属性。我不想在不了解发生了什么的情况下滥用eventAggregator在幕后。任何线索将不胜感激!

编辑

这个问题的解决办法是在

http://plnkr.co/edit/0gMZFhtKA2r6nec9kGUC?p=preview.

与我看到的问题略有不同,但子视图仍然没有反映父视图模型的变化。

【问题讨论】:

  • 对不起,我不明白你在问什么。你能用几句话概括你的问题吗?
  • 如果你有两个自定义元素,其中 element1 是 element2 的父元素,两个元素都可以访问数据对象的同一个实例,(因为它通过可绑定装饰器绑定到两个元素),如何在不使用事件聚合器的情况下观察此数据对象属性的变化?
  • 您描述的代码应该可以正常工作。我在我的应用程序中添加了类似的东西,它可以工作。您在命名(项目/产品,InEditMode/inEditMode)方面存在一些不一致 - 它只是在问题中还是在您的代码中?你在哪里调用 subscribe - in bind() 函数?无论如何,我建议您制作一个可运行的 plunkr 来说明您的问题。
  • 命名不一致只是问题,我将努力创建一个 plnkr。感谢您的评论顺便说一句

标签: aurelia


【解决方案1】:

我会推荐一种稍微不同的方法,使用BindingEngine

@bindable product;
productChanged(newValue, oldValue) {
  if (this.inEditModeSubscription) {
    this.inEditModeSubscription.dispose();
    this.inEditModeSubscription = null;
  }
  if (newValue) {
      this.inEditModeSubscription = this.bindingEngine
          .propertyObserver(newValue, "inEditMode")
          .subscribe(this.onEditModeChanged);
  }
}
inEditModeSubscription = null;

productChanged 中添加product.inEditMode 的属性观察器可确保您不会意外将观察器添加到nullundefined 对象,并且它会在您的product 出现时刷新订阅设置为不同的对象。

这可确保您的 onEditModeChanged 在属性更改时始终被触发。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    相关资源
    最近更新 更多