Aurelia中的数据绑定父子关系 [英] Data binding parent-child relationships in Aurelia
问题描述
我有两个课程:
export class Shipment {
shipmentId: number;
widget: Widget;
}
export class Widget {
widgetId: number;
name: string;
}
然后我有 ShipmentUi
具有装运实例的视图模型( this.shipment
)。
Then I have a ShipmentUi
view-model that has an instance of shipment (this.shipment
).
在 ShipmentUi
视图中,我构建了部分UI,显示允许选择Widget的WidgetUi: / p>
And in the ShipmentUi
view I compose part of the UI show the WidgetUi that allows selection of the Widget:
<compose view-model="src/views/widgetUi" model.bind="shipment"></compose>
WigetUi的视图模型可以节省发货。所以WidgetUi有一个 this.shipment
。
The WigetUi's view-model saves off the shipment. So WidgetUi has a this.shipment
.
然后widgetUi的视图显示一个选择器:
And then widgetUi's view shows a selector:
<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
类不需要查看或了解货件
。它的唯一功能是允许选择 Widget
。它不需要关心它是用于装运还是其他东西。)
This would have WidgetUi's view-model only get a this.widget
. (The WidgetUi
class does not need to see or know about the shipment
. Its sole function is to allow selecting a Widget
. It should not need to care if it is for a shipment or for something else.)
但是,正如我理解Javascript,这不会起作用。
因为如果我只是传递对shipment.widget的引用,那么WidgetUi将会有只是对小部件的引用。首先,WidgetUi的 this.widget
将与ShipmentUi的 this.shipment.widget
具有相同的参考。
Because if I just pass in the reference to shipment.widget, then WidgetUi will have just a reference to the widget part. At first WidgetUi's this.widget
will have the same reference as ShipmentUi's this.shipment.widget
.
但是当用户选择不同的小部件时,WidgetUi this.widget
将获得不同的引用(对于下拉列表中新选择的小部件) )。但是ShipmentUi的 this.shipment.widget
仍将引用原始小部件。
But when the user selects a different widget, WidgetUi this.widget
will get a different reference (to the newly selected widget in the dropdown). But ShipmentUi's this.shipment.widget
will will still reference the original widget.
在Javascript中绑定到子对象时,如果要了解子对象的交换,是否总是必须传入包含对象? ?
这个问题的原因是我的测试不是100%确定的。所以我希望有人能为我清理它。
The reason for this question is that my tests are not 100% conclusive. So I am hoping someone can clear it up for me.
我也希望我错了,因为我真的不喜欢必须公开包含类中的所有数据。 (在这种情况下,在 WigetUi
类中访问 shipping
。)
I am also hoping I am wrong somehow, as I really don't like the idea of having to expose all the data in the containing classes. (Giving access to shipment
in the WigetUi
class in this case.)
Fabio Luz请求澄清我的要求。所以这是一次尝试。这将通过上面的示例,但将其更改为我希望它工作的方式。
Fabio Luz requested some clarification on what I am asking. So here is an attempt. This walks through the example above, but changing it to the way I would LIKE it to work.
我有两个小部件。 Sharp Widget和Dull Widget。
I have two Widgets. Sharp Widget and Dull Widget.
ShipmentUi.js:
此类具有变量 this.shipment.widget
。我要说它的值是'A3'(任意内存值)。 'A3'是对名称为'Sharp Widget'的小部件的引用。
ShipmentUi.js:
This class has the variable this.shipment.widget
. I am going to say that its value is 'A3' (arbitrary memory value). 'A3' is a reference to a widget that has a name of 'Sharp Widget'.
然后我将小部件传递给WidgetUi类:
I then pass the widget down to the WidgetUi class:
<compose view-model="src/views/widgetUi" model.bind="shipment.wiget"></compose>
WidgetUi.js:
WidgetUi类has:
WidgetUi.js:
The WidgetUi class has:
activate(widget: Widget) {
this.widget = widget;
}
现在在WidgetUi this.widget
的值也为'A3'。该值是对Widget的内存引用,其名称为Sharp Widget。
So now in WidgetUi this.widget
also has a value of 'A3'. That value is a memory reference to the Widget that has a name of 'Sharp Widget'.
现在用户使用此选择
要更改小部件的元素:
Now the user uses this select
element to change the Widget:
<select value.bind="widget" >
<option class="dropdown-toggle" repeat.for="widget of widgets"
model.two-way="widget">${widget.name}</option>
</select>
这次我绑定到小部件
(而不是 this.shipment.widget
就像我上面所做的那样。)
This time I bind to widget
(instead of this.shipment.widget
like I did above).
然后用户选择一个名为'的小部件Dull Widget'使用选择
。该小部件的值为B7。 'B7'是对名为'Dull Widget'的小部件的引用。
Then user picks a widget with the name of 'Dull Widget' using the select
. That widget has a value of 'B7'. And 'B7' is a reference to the widget named 'Dull Widget'.
据我了解JavaScript,WidgetUi的 this.widget
现在的值为'B7'(这是对'Dull Widget'的引用)。 (这是通过Aurelia数据绑定系统完成的。)
As I understand JavaScript, WidgetUi's this.widget
now has a value of 'B7' (which is a reference to 'Dull Widget'). (This is done via the Aurelia data binding system.)
但ShipmentUi的 this.shipment.widget
仍然是' A3'(这是对'Sharp Widget'的引用)。
But ShipmentUi's this.shipment.widget
is still 'A3' (which is a reference to 'Sharp Widget').
当我绑定 this.shipment.widget时,这不是我想要的/ code>到
compose
元素。我希望小部件对象的更新能够反映在货件中。 (注意,如果我刚刚更新了 widget.name
,那么它就会更新。)
This is not what I wanted when I bound this.shipment.widget
to the compose
element. I wanted the updates to the widget object to be reflected in the shipment. (Note, if I had just updated widget.name
, then it would have been updated.)
所以,从我所看到的,我必须将完整的父母传递给 compose
元素( this.shipment
case),如果我想要捕获一个赋值。
So, from what I can see, I have to pass in the full parent to the compose
element (this.shipment
in this case), if I want an assignment to be captured.
我希望我错了(或者有一个解决方法),因为传递父对象让我分享细节那个孩子课不需要知道。 (即它打破了数据封装)
I am hoping I am wrong (or there is a workaround), because passing the parent object makes me share details that the "child" class does not need to know about. (ie it breaks data encapsulation)
我想我可以在我的每一层之间建立一个持有者。例如: this.shipment.holder.widget
和 holder
只包含其中的小部件。但这有点难看...我希望还有另一种方式...
I guess I could make a "holder" between each layer of my classes. For Example: this.shipment.holder.widget
and holder
would just have the widget in it. But this is kinda ugly... I hope there is another way...
所以,我的问题是:我对上述陈述是否正确? 如果我是,还有另一种保持我的对象模型干净的方法吗?
So, my question is: Am I right with my above statements? And if I am, is there another way that keeps my object model clean?
推荐答案
如果我正确理解这个问题,您正在寻找一种与widgetui组件共享最小数据量的方法。而不是给它整个货件对象,以便它可以操纵 shipment.widget
属性,而不是给它一个属性访问器来访问小部件属性。
If I understand the question correctly you're looking for a way to share the minimum amount of data with the widgetui component. Instead of giving it the whole shipment object so that it can manipulate the shipment.widget
property, you'd rather give it a property accessor to the widget property.
好消息:这正是 @bindable
的目的。您需要做的就是停止使用compose并使用 @bindable
属性创建自定义元素,这些属性表示自定义元素执行此任务所需的最小数据量。例如:
Good news: this is exactly what @bindable
is designed to do. All you'll need to do is stop using compose and craft a custom element with @bindable
properties representing the minimum amount of data the custom element needs to do it's job. For example:
widget-picker.js
import {bindable, bindingMode} from 'aurelia-framework';
export class WidgetPicker {
@bindable({ defaultBindingMode: bindingMode.twoWay }) widget;
@bindable widgets;
}
widget-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>
示例:
https://gist.run/?id=4c726da335aaecefd80b
这篇关于Aurelia中的数据绑定父子关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!