Aurelia 中的数据绑定父子关系
Data binding parent-child relationships in Aurelia
代码:
我有两个 classes:
export class Shipment {
shipmentId: number;
widget: Widget;
}
export class Widget {
widgetId: number;
name: string;
}
然后我有一个 ShipmentUi
视图模型,其中有一个发货实例 (this.shipment
)。
并且在 ShipmentUi
视图中,我组成了 UI 显示允许选择 Widget 的 WidgetUi 的一部分:
<compose view-model="src/views/widgetUi" model.bind="shipment"></compose>
WigetUi的view-model省货了。所以 WidgetUi 有一个 this.shipment
.
然后 widgetUi 的视图显示一个选择器:
<select value.bind="shipment.widget" >
<option class="dropdown-toggle" repeat.for="widget of widgets"
model.two-way="widget">${widget.name}</option>
</select>
问题设置:
在我的撰写标签中(在 ShipmentUi 的视图中),我宁愿绑定到 shipment.widget
。
这将使 WidgetUi 的视图模型仅获得 this.widget
。 (WidgetUi
class 不需要看到或知道 shipment
。它的唯一功能是允许选择 Widget
。它不需要关心它是否是用于装运或其他东西。)
但是,据我了解Javascript,这是行不通的。
因为如果我只传入对 shipment.widget 的引用,那么 WidgetUi 将只有对小部件部分的引用。首先 WidgetUi 的 this.widget
将与 ShipmentUi 的 this.shipment.widget
.
具有相同的引用
但是当用户选择不同的小部件时,WidgetUi this.widget
将获得不同的引用(对下拉列表中新选择的小部件)。但是 ShipmentUi 的 this.shipment.widget
仍将引用原始小部件。
问题:
在Javascript中绑定子对象时,想知道子对象的swap是不是一定要传入包含对象?
这个问题的原因是我的测试不是 100% 确凿的。所以我希望有人能帮我解决这个问题。
我也希望我在某种程度上是错的,因为我真的不喜欢必须公开包含 classes 中的所有数据的想法。 (在这种情况下,在 WigetUi
class 中授予对 shipment
的访问权。)
再问(澄清):
Fabio Luz 要求对我的问题进行一些澄清。所以这里是一个尝试。这遍历了上面的示例,但将其更改为我希望它工作的方式。
我有两个小部件。 Sharp Widget 和 Dull Widget。
ShipmentUi.js:
这个 class 有变量 this.shipment.widget
。我要说它的值是'A3'(任意内存值)。 'A3' 是对名称为 'Sharp Widget'.
的小部件的引用
然后我将小部件传递给 WidgetUi class:
<compose view-model="src/views/widgetUi" model.bind="shipment.wiget"></compose>
WidgetUi.js:
WidgetUi class 有:
activate(widget: Widget) {
this.widget = widget;
}
所以现在在WidgetUi中this.widget
也有'A3'的值。该值是对名称为 'Sharp Widget'.
的 Widget 的内存引用
现在用户使用这个 select
元素来更改小部件:
<select value.bind="widget" >
<option class="dropdown-toggle" repeat.for="widget of widgets"
model.two-way="widget">${widget.name}</option>
</select>
这次我绑定到 widget
(而不是像上面那样绑定到 this.shipment.widget
)。
然后用户使用 select
选择名称为 'Dull Widget' 的小部件。该小部件的值为 'B7'。 'B7' 是对名为 'Dull Widget'.
的小部件的引用
据我了解JavaScript,WidgetUi 的this.widget
现在的值为'B7'(这是对'Dull Widget' 的引用)。 (这是通过 Aurelia 数据绑定系统完成的。)
但是ShipmentUi的this.shipment.widget
仍然是'A3'(这是对'Sharp Widget'的引用)。
当我将 this.shipment.widget
绑定到 compose
元素时,这不是我想要的。我希望小部件对象的更新反映在装运中。 (注意,如果我刚刚更新 widget.name
,那么它就会更新。)
因此,据我所知,如果我想捕获一个赋值,我必须将完整的父元素传递给 compose
元素(在本例中为 this.shipment
)。
我希望我错了(或者有解决方法),因为传递父对象让我共享 "child" class 不需要知道的详细信息。 (即它破坏了数据封装)
我想我可以在我的 classes 的每一层之间做一个 "holder"。例如:this.shipment.holder.widget
和 holder
只会在其中包含小部件。但这有点丑...我希望有另一种方式...
所以,我的问题是:我的上述陈述是否正确? 如果我是,还有其他方法可以保持我的对象模型干净吗?
如果我对问题的理解正确,那么您正在寻找一种与 widgetui 组件共享最少数据量的方法。与其给它整个 shipment 对象以便它可以操作 shipment.widget
属性,不如给它一个 属性 小部件 属性.[=17 的访问器=]
好消息:这正是 @bindable
设计的目的。您需要做的就是停止使用 compose 并制作一个具有 @bindable
属性的自定义元素,该属性表示自定义元素完成其工作所需的最少数据量。例如:
小部件-picker.js
import {bindable, bindingMode} from 'aurelia-framework';
export class WidgetPicker {
@bindable({ defaultBindingMode: bindingMode.twoWay }) widget;
@bindable widgets;
}
小部件-picker.html
<select value.bind="widget">
<option repeat.for="widget of widgets" model.bind="widget">${widget.name}</option>
</select>
用法:
<widget-picker widget.bind="shipment.widget" widgets.bind="widgets"></widget-picker>
示例:
代码:
我有两个 classes:
export class Shipment {
shipmentId: number;
widget: Widget;
}
export class Widget {
widgetId: number;
name: string;
}
然后我有一个 ShipmentUi
视图模型,其中有一个发货实例 (this.shipment
)。
并且在 ShipmentUi
视图中,我组成了 UI 显示允许选择 Widget 的 WidgetUi 的一部分:
<compose view-model="src/views/widgetUi" model.bind="shipment"></compose>
WigetUi的view-model省货了。所以 WidgetUi 有一个 this.shipment
.
然后 widgetUi 的视图显示一个选择器:
<select value.bind="shipment.widget" >
<option class="dropdown-toggle" repeat.for="widget of widgets"
model.two-way="widget">${widget.name}</option>
</select>
问题设置:
在我的撰写标签中(在 ShipmentUi 的视图中),我宁愿绑定到 shipment.widget
。
这将使 WidgetUi 的视图模型仅获得 this.widget
。 (WidgetUi
class 不需要看到或知道 shipment
。它的唯一功能是允许选择 Widget
。它不需要关心它是否是用于装运或其他东西。)
但是,据我了解Javascript,这是行不通的。
因为如果我只传入对 shipment.widget 的引用,那么 WidgetUi 将只有对小部件部分的引用。首先 WidgetUi 的 this.widget
将与 ShipmentUi 的 this.shipment.widget
.
但是当用户选择不同的小部件时,WidgetUi this.widget
将获得不同的引用(对下拉列表中新选择的小部件)。但是 ShipmentUi 的 this.shipment.widget
仍将引用原始小部件。
问题:
在Javascript中绑定子对象时,想知道子对象的swap是不是一定要传入包含对象?
这个问题的原因是我的测试不是 100% 确凿的。所以我希望有人能帮我解决这个问题。
我也希望我在某种程度上是错的,因为我真的不喜欢必须公开包含 classes 中的所有数据的想法。 (在这种情况下,在 WigetUi
class 中授予对 shipment
的访问权。)
再问(澄清):
Fabio Luz 要求对我的问题进行一些澄清。所以这里是一个尝试。这遍历了上面的示例,但将其更改为我希望它工作的方式。
我有两个小部件。 Sharp Widget 和 Dull Widget。
ShipmentUi.js:
这个 class 有变量 this.shipment.widget
。我要说它的值是'A3'(任意内存值)。 'A3' 是对名称为 'Sharp Widget'.
然后我将小部件传递给 WidgetUi class:
<compose view-model="src/views/widgetUi" model.bind="shipment.wiget"></compose>
WidgetUi.js:
WidgetUi class 有:
activate(widget: Widget) {
this.widget = widget;
}
所以现在在WidgetUi中this.widget
也有'A3'的值。该值是对名称为 'Sharp Widget'.
现在用户使用这个 select
元素来更改小部件:
<select value.bind="widget" >
<option class="dropdown-toggle" repeat.for="widget of widgets"
model.two-way="widget">${widget.name}</option>
</select>
这次我绑定到 widget
(而不是像上面那样绑定到 this.shipment.widget
)。
然后用户使用 select
选择名称为 'Dull Widget' 的小部件。该小部件的值为 'B7'。 'B7' 是对名为 'Dull Widget'.
据我了解JavaScript,WidgetUi 的this.widget
现在的值为'B7'(这是对'Dull Widget' 的引用)。 (这是通过 Aurelia 数据绑定系统完成的。)
但是ShipmentUi的this.shipment.widget
仍然是'A3'(这是对'Sharp Widget'的引用)。
当我将 this.shipment.widget
绑定到 compose
元素时,这不是我想要的。我希望小部件对象的更新反映在装运中。 (注意,如果我刚刚更新 widget.name
,那么它就会更新。)
因此,据我所知,如果我想捕获一个赋值,我必须将完整的父元素传递给 compose
元素(在本例中为 this.shipment
)。
我希望我错了(或者有解决方法),因为传递父对象让我共享 "child" class 不需要知道的详细信息。 (即它破坏了数据封装)
我想我可以在我的 classes 的每一层之间做一个 "holder"。例如:this.shipment.holder.widget
和 holder
只会在其中包含小部件。但这有点丑...我希望有另一种方式...
所以,我的问题是:我的上述陈述是否正确? 如果我是,还有其他方法可以保持我的对象模型干净吗?
如果我对问题的理解正确,那么您正在寻找一种与 widgetui 组件共享最少数据量的方法。与其给它整个 shipment 对象以便它可以操作 shipment.widget
属性,不如给它一个 属性 小部件 属性.[=17 的访问器=]
好消息:这正是 @bindable
设计的目的。您需要做的就是停止使用 compose 并制作一个具有 @bindable
属性的自定义元素,该属性表示自定义元素完成其工作所需的最少数据量。例如:
小部件-picker.js
import {bindable, bindingMode} from 'aurelia-framework';
export class WidgetPicker {
@bindable({ defaultBindingMode: bindingMode.twoWay }) widget;
@bindable widgets;
}
小部件-picker.html
<select value.bind="widget">
<option repeat.for="widget of widgets" model.bind="widget">${widget.name}</option>
</select>
用法:
<widget-picker widget.bind="shipment.widget" widgets.bind="widgets"></widget-picker>
示例: