在Aurelia,我有一个由其他几个组件组成的父组件。为了简化这个例子,假设一个组件是State下拉列表,另一个组件是City下拉列表。将有其他组件依赖于所选城市,但这两个组件足以说明问题。父视图如下所示:
<template>
<compose view-model="StatePicker"></compose>
<compose view-model="CityPicker"></compose>
</template>
这个想法是你会从StatePicker中选择一个状态,然后填充CityPicker,然后你会选择一个可以填充其他组件的城市。路线看起来像/:state/:city
,两者都是可选的。如果省略:state
,则网址将自动重定向到第一个可用状态。
我使用EventAggregator在组件之间发送消息(父级在选择状态时向CityPicker发送消息)。这是有效的,除了应用程序的初始加载。父节点正在将消息发送到CityPicker,但CityPicker组件尚未激活,并且它从未收到消息。
显示问题的Here's a Plunker。您可以看到城市下拉列表初始为空,但一旦您更改状态下拉列表,它就会开始工作。观察控制台以记录消息。
所以问题是:在开始发送消息之前,有没有办法知道所有组件都已加载?我应该使用更好的技术吗?现在,StatePicker向父级发送状态已更改的消息,然后父级向CityPicker发送状态已更改的消息。这似乎有点迂回,但用户可能会在网址中输入无效状态,我喜欢能够在所有其他组件之前在一个地方(父级)验证状态的想法尝试根据它加载数据。
答案 0 :(得分:2)
您希望自定义元素以viewModel
(或Angular / MVC语言,controller
)来驱动数据。 viewModel捕获有关页面当前状态的信息。例如,您可以拥有addressViewModel
路由,其中包含state
和city
属性。然后,您可以连接自定义元素以将数据驱动到这些变量中。同样,他们可以听取有关这些变量的信息。
以下是您可能会写的一些示例:
<强> address.html 强>
<state-picker stateList.one-way="stateList" value.bind="state" change.delegate="updateCities()"></state-picker>
<city-picker cityList.one-way="cityList" value.bind="city"></city-picker>
address.js
class AddressViewModel {
state = null;
city = null;
stateList = ['Alabama', 'Alaska', 'Some others', 'Wyoming'];
cityList = [];
updateCities() {
let state = this.state;
http.get(`API/cities?state=${state}`) // get http module through dependency injection
.then((response) => {
var cities = response.content;
this.cities.length = 0; // remove current entries
Array.prototype.push.apply(this.cities, cities);
});
}
}
如果您希望获得更高级的功能并将所有州和城市逻辑隔离到各自的自定义元素中,您可以尝试遵循以下设计模式:
<强> address.html 强>
<state-picker value.bind="state" country="US"></state-picker>
<city-picker value.bind="city" state.bind="state"></city-picker>
address.js
class cityPickerViewModel {
@bindable
state = null;
cities = [];
constructor() {
// set up subscription that listens for state changes and calls the update
// cities function, see the aurelia documentation on the BindingEngine or this
// StackOverflow question:
// http://stackoverflow.com/questions/28419242/property-change-subscription-with-aurelia
}
updateCities() {
/// same as before
}
}
在这种情况下,您不希望使用EventAggregator
。 EventAggregator
最适合从一个中心位置的不同位置收集各种消息。例如,如果您有一个模块在一个通知面板中收集了应用通知。在这种情况下,通知面板不知道谁可能向其发送消息,因此它只会收集特定类型的所有消息;同样,任何组件都可以发送消息,无论是否启用了通知面板。